diff --git a/Applications/mitkDiffusion/QDiffusionImagingSplashScreen.cpp b/Applications/mitkDiffusion/QDiffusionImagingSplashScreen.cpp index f3d02621d5..7ac2793bd3 100644 --- a/Applications/mitkDiffusion/QDiffusionImagingSplashScreen.cpp +++ b/Applications/mitkDiffusion/QDiffusionImagingSplashScreen.cpp @@ -1,91 +1,106 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QDiffusionImagingSplashScreen.h" #include #include QDiffusionImagingSplashScreen::QDiffusionImagingSplashScreen(const QImage& image, QWidget* parent) :QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SplashScreen ) ,backgroundImage(image) { setAttribute(Qt::WA_TranslucentBackground); resize(image.size()); resizeEvent(NULL); } QDiffusionImagingSplashScreen::~QDiffusionImagingSplashScreen() { } QSize QDiffusionImagingSplashScreen::sizeHint() const { return backgroundImage.size(); } void QDiffusionImagingSplashScreen::paintEvent(QPaintEvent*) { QPainter painter(this); painter.drawImage( rect(), backgroundImage ); } void QDiffusionImagingSplashScreen::resizeEvent(QResizeEvent*) { setMask( createMaskRegion( backgroundImage) ); } QRegion QDiffusionImagingSplashScreen::createMaskRegion( const QImage & image, bool posMask ) { if ( image.isNull() ) return QRegion(); if (image.depth() != 32) { QImage img32 = image.convertToFormat(QImage::Format_RGB32); return createMaskRegion( img32, posMask ); } int width = image.width(); int height = image.height(); QRegion retVal; for( int y = 0; y < height; ++y ) { // guarented to be 32 bit by the check above QRgb *currLine = (QRgb *)image.scanLine( y ); int xstart = -1; int xcurr = -1; QRgb * currVal = currLine; for( int x = 0; x < width; ++x, ++currVal ) { int alpha = qAlpha( *currVal ); if ( ( posMask && alpha != 0 ) || ( !posMask && alpha == 0 ) ) { // on non-alpha pixel if ( xstart == -1 ) { // remember start of non-alpha line-segment (if necessary) xstart = x; } xcurr = x; } else // alpha-pixel if ( xcurr != -1 ) // if this alpha pixel is following a non-alpha line-segment { retVal += QRegion( xstart, y, xcurr - xstart + 1, 1 ); xstart = -1; xcurr = -1; } } if ( xcurr != -1 ) { retVal += QRegion( xstart, y, xcurr - xstart + 1, 1 ); } } return retVal; } void QDiffusionImagingSplashScreen::mouseReleaseEvent(QMouseEvent* mouseEvent) { QWidget::mouseReleaseEvent(mouseEvent); hide(); } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.cpp index 75b2459f34..2c184c90e7 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.cpp @@ -1,9 +1,24 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryBackingStoreException.h" #include namespace berry { POCO_IMPLEMENT_EXCEPTION(BackingStoreException, Poco::RuntimeException, "BackingStore Exception") } \ No newline at end of file diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.h index 054ae9460b..f68488349c 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryBackingStoreException.h @@ -1,18 +1,33 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYBACKINGSTOREEXCEPTION_H_ #define BERRYBACKINGSTOREEXCEPTION_H_ #include #include namespace berry { /** * Thrown to indicate that a preferences operation could not complete because of * a failure in the backing store, or a failure to contact the backing store. * * @version $Revision$ */ POCO_DECLARE_EXCEPTION(BERRY_RUNTIME, BackingStoreException, Poco::RuntimeException); } #endif /* BERRYBACKINGSTOREEXCEPTION_H_ */ \ No newline at end of file diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferences.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferences.h index cc47b94504..305f9263c8 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferences.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferences.h @@ -1,35 +1,50 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIBERRYPREFERENCES_H_ #define BERRYIBERRYPREFERENCES_H_ #include #include "berryIPreferences.h" #include "berryMessage.h" #include #include #include namespace berry { /// /// Like IEclipsePreferences an extension to the osgi-IPreferences /// to send out events when nodes or values changed in a node. /// struct BERRY_RUNTIME IBerryPreferences : virtual public IPreferences { berryInterfaceMacro(IBerryPreferences, berry) virtual ~IBerryPreferences(); /// /// Invoked when this node was changed, that is when a property /// was changed or when a new child node was inserted. /// berry::Message1 OnChanged; }; } // namespace berry #endif /*BERRYIBERRYPREFERENCES_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferencesService.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferencesService.h index da451625f5..6bc6c351e0 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferencesService.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIBerryPreferencesService.h @@ -1,32 +1,47 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIBERRYPREFERENCESSERVICE_H_ #define BERRYIBERRYPREFERENCESSERVICE_H_ #include "berryIPreferencesService.h" #include "Poco/File.h" #include #include namespace berry { struct IBerryPreferencesService : public IPreferencesService { berryInterfaceMacro(IBerryPreferencesService, berry) /// /// Try to import the prefs from the given file. /// Existing properties will be overridden! /// Returns true if the preferences could be imported. /// virtual void ImportPreferences(Poco::File f, std::string name="") = 0; /// /// Exports the current system preferences to the given file. /// virtual void ExportPreferences(Poco::File f, std::string name="") = 0; }; } // namespace berry #endif /*BERRYIBERRYPREFERENCESSERVICE_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferences.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferences.h index 2b2da2cedc..0a1fb24c27 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferences.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferences.h @@ -1,706 +1,721 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIPREFERENCES_H_ #define BERRYIPREFERENCES_H_ #include #include "berryObject.h" #include "berryBackingStoreException.h" #include #include #include namespace berry { /** * A node in a hierarchical collection of preference data. * *

* This interface allows applications to store and retrieve user and system * preference data. This data is stored persistently in an * implementation-dependent backing store. Typical implementations include flat * files, OS-specific registries, directory servers and SQL databases. * *

* For each bundle, there is a separate tree of nodes for each user, and one for * system preferences. The precise description of "user" and "system" will vary * from one bundle to another. Typical information stored in the user preference * tree might include font choice, and color choice for a bundle which interacts * with the user via a servlet. Typical information stored in the system * preference tree might include installation data, or things like high score * information for a game program. * *

* Nodes in a preference tree are named in a similar fashion to directories in a * hierarchical file system. Every node in a preference tree has a node name * (which is not necessarily unique), a unique absolute path name , * and a path name relative to each ancestor including itself. * *

* The root node has a node name of the empty std::string object (""). * Every other node has an arbitrary node name, specified at the time it is * created. The only restrictions on this name are that it cannot be the empty * string, and it cannot contain the slash character ('/'). * *

* The root node has an absolute path name of "/". Children of the * root node have absolute path names of "/" + <node name> * . All other nodes have absolute path names of <parent's absolute * path name> + "/" + <node name> . Note that * all absolute path names begin with the slash character. * *

* A node n 's path name relative to its ancestor a is simply the * string that must be appended to a 's absolute path name in order to * form n 's absolute path name, with the initial slash character (if * present) removed. Note that: *

    *
  • No relative path names begin with the slash character. *
  • Every node's path name relative to itself is the empty string. *
  • Every node's path name relative to its parent is its node name (except * for the root node, which does not have a parent). *
  • Every node's path name relative to the root is its absolute path name * with the initial slash character removed. *
* *

* Note finally that: *

    *
  • No path name contains multiple consecutive slash characters. *
  • No path name with the exception of the root's absolute path name end in * the slash character. *
  • Any string that conforms to these two rules is a valid path name. *
* *

* Each Preference node has zero or more properties associated with * it, where a property consists of a name and a value. The bundle writer is * free to choose any appropriate names for properties. Their values can be of * type std::string,long,int,bool, * std::vector,float, or double but they can * always be accessed as if they were std::string objects. * *

* All node name and property name comparisons are case-sensitive. * *

* All of the methods that modify preference data are permitted to operate * asynchronously; they may return immediately, and changes will eventually * propagate to the persistent backing store, with an implementation-dependent * delay. The flush method may be used to synchronously force updates * to the backing store. * *

* Implementations must automatically attempt to flush to the backing store any * pending updates for a bundle's preferences when the bundle is stopped or * otherwise ungets the IPreferences Service. * *

* The methods in this class may be invoked concurrently by multiple threads in * a single Java Virtual Machine (JVM) without the need for external * synchronization, and the results will be equivalent to some serial execution. * If this class is used concurrently by multiple JVMs that store their * preference data in the same backing store, the data store will not be * corrupted, but no other guarantees are made concerning the consistency of the * preference data. * * * @version $Revision$ */ struct BERRY_RUNTIME IPreferences : virtual public Object { berryInterfaceMacro(IPreferences, berry) virtual ~IPreferences(); /** * Associates the specified value with the specified key in this node. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @throws NullPointerException if key or value is * null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. */ virtual void Put(std::string key, std::string value) = 0; /** * Returns the value associated with the specified key in this * node. Returns the specified default if there is no value associated with * the key, or the backing store is inaccessible. * * @param key key whose associated value is to be returned. * @param def the value to be returned in the event that this node has no * value associated with key or the backing store is * inaccessible. * @return the value associated with key, or def if * no value is associated with key. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @throws NullPointerException if key is null. (A * null default is permitted.) */ virtual std::string Get(std::string key, std::string def) const = 0; /** * Removes the value associated with the specified key in this * node, if any. * * @param key key whose mapping is to be removed from this node. * @see #get(std::string,std::string) * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. */ virtual void Remove(std::string key) = 0; /** * Removes all of the properties (key-value associations) in this node. This * call has no effect on any descendants of this node. * * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #remove(std::string) */ virtual void Clear() throw(Poco::Exception, BackingStoreException) = 0; /** * Associates a std::string object representing the specified * int value with the specified key in this node. The * associated string is the one that would be returned if the int * value were passed to Integer.toString(int). This method is * intended for use in conjunction with {@link #getInt}method. * *

* Implementor's note: it is not necessary that the property value * be represented by a std::string object in the backing store. If the * backing store supports integer values, it is not unreasonable to use * them. This implementation detail is not visible through the * IPreferences API, which allows the value to be read as an * int (with getInt or a std::string (with * get) type. * * @param key key with which the string form of value is to be associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getInt(std::string,int) */ virtual void PutInt(std::string key, int value) = 0; /** * Returns the int value represented by the std::string * object associated with the specified key in this node. The * std::string object is converted to an int as by * Integer.parseInt(std::string). Returns the specified default if * there is no value associated with the key, the backing store * is inaccessible, or if Integer.parseInt(std::string) would throw a * NumberFormatException if the associated value were * passed. This method is intended for use in conjunction with the * {@link #putInt}method. * * @param key key whose associated value is to be returned as an * int. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as an int or the backing store is * inaccessible. * @return the int value represented by the std::string * object associated with key in this node, or * def if the associated value does not exist or cannot * be interpreted as an int type. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #putInt(std::string,int) * @see #get(std::string,std::string) */ virtual int GetInt(std::string key, int def) const = 0; /** * Associates a std::string object representing the specified * long value with the specified key in this node. The * associated std::string object is the one that would be returned if * the long value were passed to Long.toString(long). * This method is intended for use in conjunction with the {@link #getLong} * method. * *

* Implementor's note: it is not necessary that the value * be represented by a std::string type in the backing store. If the * backing store supports long values, it is not unreasonable to * use them. This implementation detail is not visible through the * IPreferences API, which allows the value to be read as a * long (with getLong or a std::string (with * get) type. * * @param key key with which the string form of value * is to be associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getLong(std::string,long) */ virtual void PutLong(std::string key, long value) = 0; /** * Returns the long value represented by the std::string * object associated with the specified key in this node. The * std::string object is converted to a long as by * Long.parseLong(std::string). Returns the specified default if * there is no value associated with the key, the backing store * is inaccessible, or if Long.parseLong(std::string) would throw a * NumberFormatException if the associated value were * passed. This method is intended for use in conjunction with the * {@link #putLong}method. * * @param key key whose associated value is to be returned as a * long value. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as a long type or the backing * store is inaccessible. * @return the long value represented by the std::string * object associated with key in this node, or * def if the associated value does not exist or cannot * be interpreted as a long type. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #putLong(std::string,long) * @see #get(std::string,std::string) */ virtual long GetLong(std::string key, long def) const = 0; /** * Associates a std::string object representing the specified * bool value with the specified key in this node. The * associated string is "true" if the value is true, and "false" * if it is false. This method is intended for use in * conjunction with the {@link #getBool}method. * *

* Implementor's note: it is not necessary that the value be * represented by a string in the backing store. If the backing store * supports bool values, it is not unreasonable to use them. * This implementation detail is not visible through the IPreferences * API, which allows the value to be read as a bool * (with getBool) or a std::string (with get) * type. * * @param key key with which the string form of value is to be * associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getBool(std::string,bool) * @see #get(std::string,std::string) */ virtual void PutBool(std::string key, bool value) = 0; /** * Returns the bool value represented by the std::string * object associated with the specified key in this node. Valid * strings are "true", which represents true, and "false", which * represents false. Case is ignored, so, for example, "TRUE" * and "False" are also valid. This method is intended for use in * conjunction with the {@link #putBool}method. * *

* Returns the specified default if there is no value associated with the * key, the backing store is inaccessible, or if the associated * value is something other than "true" or "false", ignoring case. * * @param key key whose associated value is to be returned as a * bool. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as a bool or the backing store * is inaccessible. * @return the bool value represented by the std::string * object associated with key in this node, or * null if the associated value does not exist or cannot * be interpreted as a bool. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #get(std::string,std::string) * @see #putBool(std::string,bool) */ virtual bool GetBool(std::string key, bool def) const = 0; /** * Associates a std::string object representing the specified * float value with the specified key in this node. * The associated std::string object is the one that would be returned * if the float value were passed to * Float.toString(float). This method is intended for use in * conjunction with the {@link #getFloat}method. * *

* Implementor's note: it is not necessary that the value be * represented by a string in the backing store. If the backing store * supports float values, it is not unreasonable to use them. * This implementation detail is not visible through the IPreferences * API, which allows the value to be read as a float (with * getFloat) or a std::string (with get) type. * * @param key key with which the string form of value is to be * associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getFloat(std::string,float) */ virtual void PutFloat(std::string key, float value) = 0; /** * Returns the float value represented by the std::string * object associated with the specified key in this node. The * std::string object is converted to a float value as by * Float.parseFloat(std::string). Returns the specified default if * there is no value associated with the key, the backing store * is inaccessible, or if Float.parseFloat(std::string) would throw a * NumberFormatException if the associated value were passed. * This method is intended for use in conjunction with the {@link #putFloat} * method. * * @param key key whose associated value is to be returned as a * float value. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as a float type or the backing * store is inaccessible. * @return the float value represented by the string associated * with key in this node, or def if the * associated value does not exist or cannot be interpreted as a * float type. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @throws NullPointerException if key is null. * @see #putFloat(std::string,float) * @see #get(std::string,std::string) */ virtual float GetFloat(std::string key, float def) const = 0; /** * Associates a std::string object representing the specified * double value with the specified key in this node. * The associated std::string object is the one that would be returned * if the double value were passed to * Double.toString(double). This method is intended for use in * conjunction with the {@link #getDouble}method * *

* Implementor's note: it is not necessary that the value be * represented by a string in the backing store. If the backing store * supports double values, it is not unreasonable to use them. * This implementation detail is not visible through the IPreferences * API, which allows the value to be read as a double (with * getDouble) or a std::string (with get) * type. * * @param key key with which the string form of value is to be * associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key is null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getDouble(std::string,double) */ virtual void PutDouble(std::string key, double value) = 0; /** * Returns the double value represented by the std::string * object associated with the specified key in this node. The * std::string object is converted to a double value as by * Double.parseDouble(std::string). Returns the specified default if * there is no value associated with the key, the backing store * is inaccessible, or if Double.parseDouble(std::string) would throw * a NumberFormatException if the associated value were passed. * This method is intended for use in conjunction with the * {@link #putDouble}method. * * @param key key whose associated value is to be returned as a * double value. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as a double type or the backing * store is inaccessible. * @return the double value represented by the std::string * object associated with key in this node, or * def if the associated value does not exist or cannot * be interpreted as a double type. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the the {@link #removeNode()}method. * @throws NullPointerException if key is null. * @see #putDouble(std::string,double) * @see #get(std::string,std::string) */ virtual double GetDouble(std::string key, double def) const = 0; /** * Associates a std::string object representing the specified * std::vector with the specified key in this node. The * associated std::string object the Base64 encoding of the * std::vector, as defined in RFC 2045 , Section 6.8, * with one minor change: the string will consist solely of characters from * the Base64 Alphabet ; it will not contain any newline characters. * This method is intended for use in conjunction with the * {@link #getByteArray}method. * *

* Implementor's note: it is not necessary that the value be * represented by a std::string type in the backing store. If the * backing store supports std::vector values, it is not unreasonable * to use them. This implementation detail is not visible through the * IPreferences API, which allows the value to be read as an a * std::vector object (with getByteArray) or a * std::string object (with get). * * @param key key with which the string form of value * is to be associated. * @param value value whose string form is to be associated with * key. * @throws NullPointerException if key or value is * null. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #getByteArray(std::string,std::vector) * @see #get(std::string,std::string) */ virtual void PutByteArray(std::string key, std::string value) = 0; /** * Returns the std::vector value represented by the std::string * object associated with the specified key in this node. Valid * std::string objects are Base64 encoded binary data, as * defined in RFC 2045 , * Section 6.8, with one minor change: the string must consist solely of * characters from the Base64 Alphabet ; no newline characters or * extraneous characters are permitted. This method is intended for use in * conjunction with the {@link #putByteArray}method. * *

* Returns the specified default if there is no value associated with the * key, the backing store is inaccessible, or if the associated * value is not a valid Base64 encoded byte array (as defined above). * * @param key key whose associated value is to be returned as a * std::vector object. * @param def the value to be returned in the event that this node has no * value associated with key or the associated value * cannot be interpreted as a std::vector type, or the backing * store is inaccessible. * @return the std::vector value represented by the std::string * object associated with key in this node, or * def if the associated value does not exist or cannot * be interpreted as a std::vector. * @throws NullPointerException if key is null. (A * null value for def is permitted.) * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #get(std::string,std::string) * @see #putByteArray(std::string,std::vector) */ virtual std::string GetByteArray(std::string key, std::string def) const = 0; /** * Returns all of the keys that have an associated value in this node. (The * returned array will be of size zero if this node has no preferences and * not null!) * * @return an array of the keys that have an associated value in this node. * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. */ virtual std::vector Keys() const throw(Poco::Exception, BackingStoreException) = 0; /** * Returns the names of the children of this node. (The returned array will * be of size zero if this node has no children and not null!) * * @return the names of the children of this node. * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. */ virtual std::vector ChildrenNames() const throw(Poco::Exception, BackingStoreException) = 0; /** * Returns the parent of this node, or null if this is the root. * * @return the parent of this node. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. */ virtual IPreferences::Pointer Parent() const = 0; /** * Returns a named IPreferences object (node), creating it and any * of its ancestors if they do not already exist. Accepts a relative or * absolute pathname. Absolute pathnames (which begin with '/') * are interpreted relative to the root of this node. Relative pathnames * (which begin with any character other than '/') are * interpreted relative to this node itself. The empty string ("") * is a valid relative pathname, referring to this node itself. * *

* If the returned node did not exist prior to this call, this node and any * ancestors that were created by this call are not guaranteed to become * persistent until the flush method is called on the returned * node (or one of its descendants). * * @param pathName the path name of the IPreferences object to * return. * @return the specified IPreferences object. * @throws IllegalArgumentException if the path name is invalid. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @throws NullPointerException if path name is null. * @see #flush() */ virtual IPreferences::Pointer Node(std::string pathName) = 0; /** * Returns true if the named node exists. Accepts a relative or absolute * pathname. Absolute pathnames (which begin with '/') are * interpreted relative to the root of this node. Relative pathnames (which * begin with any character other than '/') are interpreted * relative to this node itself. The pathname "" is valid, and * refers to this node itself. * *

* If this node (or an ancestor) has already been removed with the * {@link #removeNode()}method, it is legal to invoke this method, * but only with the pathname ""; the invocation will return * false. Thus, the idiom p.nodeExists("") may be * used to test whether p has been removed. * * @param pathName the path name of the node whose existence is to be * checked. * @return true if the specified node exists. * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method and * pathname is not the empty string (""). * @throws IllegalArgumentException if the path name is invalid (i.e., it * contains multiple consecutive slash characters, or ends with a * slash character and is more than one character long). */ virtual bool NodeExists(std::string pathName) const throw(Poco::Exception, BackingStoreException) = 0; /** * Removes this node and all of its descendants, invalidating any properties * contained in the removed nodes. Once a node has been removed, attempting * any method other than name(),absolutePath() or * nodeExists("") on the corresponding IPreferences * instance will fail with an IllegalStateException. (The * methods defined on Object can still be invoked on a node after * it has been removed; they will not throw IllegalStateException.) * *

* The removal is not guaranteed to be persistent until the flush * method is called on the parent of this node. * * @throws IllegalStateException if this node (or an ancestor) has already * been removed with the {@link #removeNode()}method. * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @see #flush() */ virtual void RemoveNode() throw(Poco::Exception, BackingStoreException) = 0; /** * Returns this node's name, relative to its parent. * * @return this node's name, relative to its parent. */ virtual std::string Name() const = 0; /** * Returns this node's absolute path name. Note that: *

    *
  • Root node - The path name of the root node is "/". *
  • Slash at end - Path names other than that of the root node may not * end in slash ('/'). *
  • Unusual names -"." and ".." have no * special significance in path names. *
  • Illegal names - The only illegal path names are those that contain * multiple consecutive slashes, or that end in slash and are not the root. *
* * @return this node's absolute path name. */ virtual std::string AbsolutePath() const = 0; /** * Forces any changes in the contents of this node and its descendants to * the persistent store. * *

* Once this method returns successfully, it is safe to assume that all * changes made in the subtree rooted at this node prior to the method * invocation have become permanent. * *

* Implementations are free to flush changes into the persistent store at * any time. They do not need to wait for this method to be called. * *

* When a flush occurs on a newly created node, it is made persistent, as * are any ancestors (and descendants) that have yet to be made persistent. * Note however that any properties value changes in ancestors are not * guaranteed to be made persistent. * * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #sync() */ virtual void Flush() throw(Poco::Exception, BackingStoreException) = 0; /** * Ensures that future reads from this node and its descendants reflect any * changes that were committed to the persistent store (from any VM) prior * to the sync invocation. As a side-effect, forces any changes * in the contents of this node and its descendants to the persistent store, * as if the flush method had been invoked on this node. * * @throws BackingStoreException if this operation cannot be completed due * to a failure in the backing store, or inability to communicate * with it. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()}method. * @see #flush() */ virtual void Sync() throw(Poco::Exception, BackingStoreException) = 0; }; } // namespace berry #endif /*BERRYIPREFERENCES_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.cpp index 4c42680874..5d332f9921 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.cpp @@ -1,8 +1,23 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryIPreferencesService.h" namespace berry { const std::string IPreferencesService::ID = "org.blueberry.core.runtime.preferences"; } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.h index 8d490f8139..ff37e35ea7 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/berryIPreferencesService.h @@ -1,65 +1,80 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIPREFERENCESSERVICE_H_ #define BERRYIPREFERENCESSERVICE_H_ #include "service/berryService.h" #include #include "berryIPreferences.h" #include #include #include namespace berry { /** * The Preferences Service. * *

* Each bundle using this service has its own set of preference trees: one for * system preferences, and one for each user. * *

* A PreferencesService object is specific to the bundle which * obtained it from the service registry. If a bundle wishes to allow another * bundle to access its preferences, it should pass its * PreferencesService object to that bundle. * */ struct BERRY_RUNTIME IPreferencesService : public Service { /// /// A unique ID for the Service. /// static const std::string ID; berryInterfaceMacro(IPreferencesService, berry) /** * Returns the root system node for the calling bundle. * * @return The root system node for the calling bundle. */ virtual IPreferences::Pointer GetSystemPreferences() = 0; /** * Returns the root node for the specified user and the calling bundle. * * @param name The user for which to return the preference root node. * @return The root node for the specified user and the calling bundle. */ virtual IPreferences::Pointer GetUserPreferences(std::string name) = 0; /** * Returns the names of users for which node trees exist. * * @return The names of users for which node trees exist. */ virtual std::vector GetUsers() const = 0; }; } // namespace berry Q_DECLARE_INTERFACE(berry::IPreferencesService, "org.blueberry.service.IPreferencesService") #endif /*BERRYIPREFERENCESSERVICE_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.cpp index c05457f975..57bb6848cd 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.cpp @@ -1,34 +1,49 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryAbstractPreferencesStorage.h" using namespace std; namespace berry { AbstractPreferencesStorage::AbstractPreferencesStorage( const Poco::File& _File ) : m_File(_File) , m_Root(0) { } AbstractPreferencesStorage::~AbstractPreferencesStorage() { } IPreferences::Pointer AbstractPreferencesStorage::GetRoot() const { return m_Root; } const Poco::File& AbstractPreferencesStorage::GetFile() const { return m_File; } void AbstractPreferencesStorage::SetFile( const Poco::File& f ) { m_File = f; } } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.h index a348b6345f..da114f81fa 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryAbstractPreferencesStorage.h @@ -1,64 +1,79 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYABSTRACTPREFERENCESSTORAGE_H_ #define BERRYABSTRACTPREFERENCESSTORAGE_H_ #include #include "berryIPreferences.h" #include "Poco/File.h" namespace berry { /// /// Interface to flush Preferences. /// class BERRY_RUNTIME AbstractPreferencesStorage : public Object { public: berryObjectMacro(berry::AbstractPreferencesStorage) /// /// Saves the path, sets the root initially to 0. /// In subclasses try to read data from file here. /// AbstractPreferencesStorage(const Poco::File& _File); /// /// Pure virtual (abstract class) /// virtual ~AbstractPreferencesStorage(); /// /// Flushes the given (or all) prefs persistently /// virtual void Flush(IPreferences* prefs) throw(Poco::Exception, BackingStoreException) = 0; /// /// Returns the root prefs /// virtual IPreferences::Pointer GetRoot() const; /// /// Returns the path of the file /// virtual const Poco::File& GetFile() const; /// /// Sets the file /// virtual void SetFile(const Poco::File& f); protected: /// /// Path to the file where the data is stored /// Poco::File m_File; /// /// Pointer to the root Preferences /// IPreferences::Pointer m_Root; }; } #endif /* BERRYABSTRACTPREFERENCESSTORAGE_H_ */ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.cpp index 7d7d438028..b8de58021a 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.cpp @@ -1,625 +1,640 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryPreferences.h" #include "berryAbstractPreferencesStorage.h" #include "Poco/ScopedLock.h" #include using namespace std; namespace berry { Preferences::Preferences(const PropertyMap& _Properties , const std::string& _Name , Preferences* _Parent , AbstractPreferencesStorage* _Storage) : m_Properties(_Properties) , m_Name(_Name) , m_Parent(_Parent) , m_Removed(false) , m_Storage(_Storage) { // root node if parent is 0 if (_Parent != 0) { m_Path = _Parent->AbsolutePath() + (_Parent->AbsolutePath() == "/" ? "": "/") + _Name; // save as child in parent _Parent->m_Children.push_back(Preferences::Pointer(this)); m_Root = _Parent->m_Root; } else { // root path m_Path = "/"; m_Root = this; } } bool Preferences::Has( string key ) const { Poco::ScopedLock scopedMutex(m_Mutex); return (m_Properties.find(key) != m_Properties.end()); } bool Preferences::IsDirty() const { Poco::ScopedLock scopedMutex(m_Mutex); bool dirty = m_Dirty; for (ChildrenList::const_iterator it = m_Children.begin() ; it != m_Children.end(); ++it) { // break condition: if one node is dirty the whole tree is dirty if(dirty) break; else dirty = (*it)->IsDirty(); } return dirty; } string Preferences::ToString() const { Poco::ScopedLock scopedMutex(m_Mutex); ostringstream s; std::locale C("C"); s.imbue(C); s << "Preferences[" << m_Path << "]"; return s.str(); } bool Preferences::Equals(const Preferences* rhs) const { Poco::ScopedLock scopedMutex(m_Mutex); if(rhs == 0) return false; return (this->m_Path == rhs->m_Path); } Preferences::PropertyMap Preferences::GetProperties() const { return m_Properties; } Preferences::ChildrenList Preferences::GetChildren() const { return m_Children; } string Preferences::AbsolutePath() const { Poco::ScopedLock scopedMutex(m_Mutex); return m_Path; } vector Preferences::ChildrenNames() const throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); vector names; for (ChildrenList::const_iterator it = m_Children.begin() ; it != m_Children.end(); ++it) { names.push_back((*it)->Name()); } return names; } AbstractPreferencesStorage* Preferences::GetStorage() const { return m_Storage; } void Preferences::Clear() throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); m_Properties.clear(); this->SetDirty(true); } void Preferences::Flush() throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); // ensure that this is the parent m_Storage->Flush(this); // if something is written, make the tree undirty this->SetDirty(false); } string Preferences::Get(string key, string def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? m_Properties.find(key)->second: def; } bool Preferences::GetBool(string key, bool def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? (m_Properties.find(key)->second == "true"? true: false): def; } string Preferences::GetByteArray(string key, string def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? Base64::decode(m_Properties.find(key)->second): def; } double Preferences::GetDouble(string key, double def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? atof(m_Properties.find(key)->second.c_str()): def; } float Preferences::GetFloat(string key, float def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? static_cast(atof(m_Properties.find(key)->second.c_str())): def; } int Preferences::GetInt(string key, int def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? atoi(m_Properties.find(key)->second.c_str()): def; } long Preferences::GetLong(string key, long def) const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return this->Has(key)? atol(m_Properties.find(key)->second.c_str()): def; } vector Preferences::Keys() const throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); vector keys; for (PropertyMap::const_iterator it = m_Properties.begin() ; it != m_Properties.end(); it++) { keys.push_back(it->first); } return keys; } string Preferences::Name() const { Poco::ScopedLock scopedMutex(m_Mutex); return m_Name; } IPreferences::Pointer Preferences::Node(string pathName) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); AssertPath(pathName); IPreferences::Pointer node; // self reference if(pathName == "") return IPreferences::Pointer(this); // absolute path else if(pathName[0] == '/') { pathName = pathName.substr(1); // call root with this relative path return m_Root->Node(pathName); } // relative path else { // check if pathName contains anymore names string name = pathName; // create new child nodes as long as there are names in the path string::size_type pos = pathName.find("/"); // cut from the beginning if(pos != string::npos) { name = pathName.substr(0, pos); pathName = pathName.substr(pos+1); } // now check if node exists->if not: make new for (ChildrenList::iterator it = m_Children.begin() ; it != m_Children.end(); it++) { // node found if((*it)->Name() == name && (*it)->IsRemoved() == false) { node = IPreferences::Pointer((*it).GetPointer()); break; } } // node not found create new one if(node.IsNull()) { // the new node automatically pushes itself into the children array of *this* Preferences::Pointer newNode(new Preferences(PropertyMap(), name, this, m_Storage)); node = newNode.GetPointer(); // this branch is dirty now -> prefs must be rewritten persistently this->SetDirty(true); } // call Node() again if there are any names left on the path if(pos != string::npos) node = node->Node(pathName); } return node; } bool Preferences::NodeExists(string pathName) const throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); AssertPath(pathName); bool nodeExists = false; // absolute path if(pathName[0] == '/') { pathName = pathName.substr(1); // call root with this relative path return m_Root->NodeExists(pathName); } // relative path else { // check if pathName contains anymore names string name = pathName; // create new child nodes as long as there are names in the path string::size_type pos = pathName.find_first_of("/"); // cut from the beginning if(pos != string::npos) { name = pathName.substr(0, pos); pathName = pathName.substr(pos+1); } // now check if node exists->if not: make new for (ChildrenList::const_iterator it = m_Children.begin() ; it != m_Children.end(); it++) { // node found if((*it)->Name() == name) { // call recursively if more names on the path exist if(pos != string::npos) nodeExists = (*it)->NodeExists(pathName); else nodeExists = true; break; } } } return nodeExists; } void Preferences::Put(string key, string value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); m_Properties[key] = value; this->SetDirty(true); } void Preferences::PutByteArray(string key, string value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, Base64::encode(value)); } void Preferences::PutBool(string key, bool value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, value ? "true" : "false"); } void Preferences::PutDouble(string key, double value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, Preferences::ToString(value)); } void Preferences::PutFloat(string key, float value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, Preferences::ToString(value)); } void Preferences::PutInt(string key, int value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, Preferences::ToString(value)); } void Preferences::PutLong(string key, long value) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Put(key, Preferences::ToString(value)); } void Preferences::Remove(string key) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); PropertyMap::iterator it = m_Properties.find(key); if(it != m_Properties.end()) m_Properties.erase(it); } void Preferences::RemoveNode() throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->SetRemoved(true); m_Parent->m_Children.erase(std::find(m_Parent->m_Children.begin(), m_Parent->m_Children.end(), Preferences::Pointer(this))); } void Preferences::Sync() throw(Poco::Exception, BackingStoreException) { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); this->Flush(); } void Preferences::AssertValid() const { Poco::ScopedLock scopedMutex(m_Mutex); if(m_Removed) { ostringstream s; std::locale C("C"); s.imbue(C); s << "no node at '" << m_Path << "'"; throw Poco::IllegalStateException(s.str()); } } void Preferences::AssertPath(string pathName) { if(pathName.find("//") != string::npos) { ostringstream s; std::locale C("C"); s.imbue(C); s << "Illegal // in m_Path m_Name '" << pathName << "'"; throw invalid_argument(s.str()); } string::size_type strLength = pathName.length(); if(pathName.length() > 1 && pathName[strLength-1] == '/') { ostringstream s; std::locale C("C"); s.imbue(C); s << "Trailing / in m_Path m_Name '" << pathName << "'"; throw invalid_argument(s.str()); } } IPreferences::Pointer Preferences::Parent() const { Poco::ScopedLock scopedMutex(m_Mutex); AssertValid(); return IPreferences::Pointer(m_Parent); } void Preferences::SetDirty( bool _Dirty ) { Poco::ScopedLock scopedMutex(m_Mutex); m_Dirty = _Dirty; if(_Dirty) this->OnChanged.Send(this); /* for (ChildrenList::iterator it = m_Children.begin() ; it != m_Children.end(); ++it) { (*it)->SetDirty(_Dirty); } */ } void Preferences::SetRemoved( bool _Removed ) { Poco::ScopedLock scopedMutex(m_Mutex); m_Removed = _Removed; for (ChildrenList::iterator it = m_Children.begin() ; it != m_Children.end(); ++it) { (*it)->SetRemoved(_Removed); } } /* Preferences::ChildrenList& Preferences::GetChildren() const { return m_Children; }*/ bool Preferences::IsRemoved() const { Poco::ScopedLock scopedMutex(m_Mutex); return m_Removed; } Preferences::~Preferences() { } } namespace Base64 { string encode(const string &sString) { static const string base64Table( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ); static const char fillChar = '='; string::size_type length = sString.length(); string result; // Allocate memory for the converted string result.reserve(length * 8 / 6 + 1); for(string::size_type nPos = 0; nPos < length; nPos++) { char code; // Encode the first 6 bits code = (sString[nPos] >> 2) & 0x3f; result.append(1, base64Table[code]); // Encode the remaining 2 bits with the next 4 bits (if present) code = (sString[nPos] << 4) & 0x3f; if(++nPos < length) code |= (sString[nPos] >> 4) & 0x0f; result.append(1, base64Table[code]); if(nPos < length) { code = (sString[nPos] << 2) & 0x3f; if(++nPos < length) code |= (sString[nPos] >> 6) & 0x03; result.append(1, base64Table[code]); } else { ++nPos; result.append(1, fillChar); } if(nPos < length) { code = sString[nPos] & 0x3f; result.append(1, base64Table[code]); } else { result.append(1, fillChar); } } return result; } string decode(const string &sString) { static const string::size_type np = string::npos; static const string::size_type DecodeTable[] = { // 0 1 2 3 4 5 6 7 8 9 np, np, np, np, np, np, np, np, np, np, // 0 - 9 np, np, np, np, np, np, np, np, np, np, // 10 - 19 np, np, np, np, np, np, np, np, np, np, // 20 - 29 np, np, np, np, np, np, np, np, np, np, // 30 - 39 np, np, np, 62, np, np, np, 63, 52, 53, // 40 - 49 54, 55, 56, 57, 58, 59, 60, 61, np, np, // 50 - 59 np, np, np, np, np, 0, 1, 2, 3, 4, // 60 - 69 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 70 - 79 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 80 - 89 25, np, np, np, np, np, np, 26, 27, 28, // 90 - 99 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 - 109 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 - 119 49, 50, 51, np, np, np, np, np, np, np, // 120 - 129 np, np, np, np, np, np, np, np, np, np, // 130 - 139 np, np, np, np, np, np, np, np, np, np, // 140 - 149 np, np, np, np, np, np, np, np, np, np, // 150 - 159 np, np, np, np, np, np, np, np, np, np, // 160 - 169 np, np, np, np, np, np, np, np, np, np, // 170 - 179 np, np, np, np, np, np, np, np, np, np, // 180 - 189 np, np, np, np, np, np, np, np, np, np, // 190 - 199 np, np, np, np, np, np, np, np, np, np, // 200 - 209 np, np, np, np, np, np, np, np, np, np, // 210 - 219 np, np, np, np, np, np, np, np, np, np, // 220 - 229 np, np, np, np, np, np, np, np, np, np, // 230 - 239 np, np, np, np, np, np, np, np, np, np, // 240 - 249 np, np, np, np, np, np // 250 - 256 }; static const char fillChar = '='; string::size_type length = sString.length(); string result; result.reserve(length); for(string::size_type nPos = 0; nPos < length; nPos++) { unsigned char c, c1; c = (char) DecodeTable[(unsigned char)sString[nPos]]; nPos++; c1 = (char) DecodeTable[(unsigned char)sString[nPos]]; c = (c << 2) | ((c1 >> 4) & 0x3); result.append(1, c); if(++nPos < length) { c = sString[nPos]; if(fillChar == c) break; c = (char) DecodeTable[(unsigned char)sString[nPos]]; c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); result.append(1, c1); } if(++nPos < length) { c1 = sString[nPos]; if(fillChar == c1) break; c1 = (char) DecodeTable[(unsigned char)sString[nPos]]; c = ((c << 6) & 0xc0) | c1; result.append(1, c); } } return result; } } ostream& operator<<( ostream& os,const berry::Preferences& m ) { std::locale C("C"); std::locale originalLocale = os.getloc(); os.imbue(C); os << m.ToString(); os.imbue(originalLocale); return os; } ostream& operator<<( ostream& os,const berry::Preferences* m ) { std::locale C("C"); std::locale originalLocale = os.getloc(); os.imbue(C); os << m->ToString(); os.imbue(originalLocale); return os; } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.h index cd2daa9f80..bdc4e72e81 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferences.h @@ -1,327 +1,342 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYPREFERENCES_H_ #define BERRYPREFERENCES_H_ #include #include "berryIBerryPreferences.h" #include #include #include #include #include "Poco/Mutex.h" namespace berry { class AbstractPreferencesStorage; /// /// Implementation of the OSGI Preferences Interface. /// Wraps a DOMNode. /// class BERRY_RUNTIME Preferences: public IBerryPreferences { public: /// /// For use with berry::SmartPtr /// berryObjectMacro(berry::Preferences) /// /// Maps a string key to a string value /// typedef std::map PropertyMap; /// /// The list of Child nodes /// typedef std::vector ChildrenList; /// /// Constructs a new preference node. /// \param _Properties the key->value pairs of this preference node /// \param _Path the absolute path to this node, e.g. "/general/editors/font" /// \param _Name the name of this node, e.g. "font" /// \param _FileName the absolute path to the file in which this preferences tree will be saved to /// \param _Parent the parent node or 0 if this is the root /// \param _Root the root of this preference tree /// Preferences(const PropertyMap& _Properties , const std::string& _Name , Preferences* _Parent , AbstractPreferencesStorage* _Storage); /// /// Nothing to do here /// virtual ~Preferences(); /// /// Prints out the absolute path of the preference node. /// std::string ToString() const; /// /// Returns if this node and his silblings have to be rewritten persistently /// bool IsDirty() const; /// /// Returns if this node is removed /// bool IsRemoved() const; /// /// Returns if this node has property with a specific key /// bool Has(std::string key) const; /// /// Returns true if the absolute paths are the same /// bool Equals(const Preferences* rhs) const; /// /// Returns all Properties as map. /// PropertyMap GetProperties() const; /// /// Returns a reference to the children list in order to add or remove nodes. /// *ATTENTION*: Should only be used /// when constructing the preferences tree from a persistent location. Normally, one would /// only use the IPreferences methods /// ChildrenList GetChildren() const; //# Begin of IPreferences methods /// /// \see IPreferences::AbsolutePath() /// virtual std::string AbsolutePath() const; /// /// \see IPreferences::ChildrenNames() /// virtual std::vector ChildrenNames() const throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::ChildrenNames() /// virtual AbstractPreferencesStorage* GetStorage() const; /// /// \see IPreferences::Clear() /// virtual void Clear() throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::Flush() /// virtual void Flush() throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::Get() /// virtual std::string Get(std::string key, std::string def) const; /// /// \see IPreferences::GetBool() /// virtual bool GetBool(std::string key, bool def) const; /// /// \see IPreferences::GetByteArray() /// virtual std::string GetByteArray(std::string key, std::string def) const; /// /// \see IPreferences::GetDouble() /// virtual double GetDouble(std::string key, double def) const; /// /// \see IPreferences::GetFloat() /// virtual float GetFloat(std::string key, float def) const; /// /// \see IPreferences::GetInt() /// virtual int GetInt(std::string key, int def) const; /// /// \see IPreferences::GetLong() /// virtual long GetLong(std::string key, long def) const; /// /// \see IPreferences::Keys() /// std::vector Keys() const throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::Name() /// virtual std::string Name() const; /// /// \see IPreferences::Node() /// virtual IPreferences::Pointer Node(std::string pathName); /// /// \see IPreferences::NodeExists() /// virtual bool NodeExists(std::string pathName) const throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::Parent() /// virtual IPreferences::Pointer Parent() const; /// /// \see IPreferences::Put() /// virtual void Put(std::string key, std::string value); /// /// \see IPreferences::PutByteArray() /// virtual void PutByteArray(std::string key, std::string value); /// /// \see IPreferences::PutBool() /// virtual void PutBool(std::string key, bool value); /// /// \see IPreferences::PutDouble() /// virtual void PutDouble(std::string key, double value); /// /// \see IPreferences::Sync() /// virtual void PutFloat(std::string key, float value); /// /// \see IPreferences::PutInt() /// virtual void PutInt(std::string key, int value); /// /// \see IPreferences::PutLong() /// virtual void PutLong(std::string key, long value); /// /// \see IPreferences::Remove() /// virtual void Remove(std::string key); /// /// \see IPreferences::RemoveNode() /// virtual void RemoveNode() throw(Poco::Exception, BackingStoreException); /// /// \see IPreferences::Sync() /// virtual void Sync() throw(Poco::Exception, BackingStoreException); //# End of IPreferences methods protected: /// /// Checks if this node is about to be removed. /// \throws IllegalStateException /// void AssertValid() const; /// /// Checks a path value for validity. /// \throws invalid_argument /// static void AssertPath(std::string pathName); /// /// Converts any value to a string (using stream operator "<<") /// template static std::string ToString(const T& obj, int precision = 12 ) { std::ostringstream s; std::locale C("C"); s.imbue(C); s.precision(precision); s << obj; return s.str(); } /// /// Sets the dirty flag recursively on all child nodes. /// void SetDirty(bool _Dirty); /// /// Sets the removed flag recursively on all child nodes. /// void SetRemoved(bool _Removed); protected: /// /// Holds all Key/Value Pairs. /// std::map m_Properties; /// /// Holds all child nodes (explicit ownership). /// std::vector m_Children; /// /// Saves the absolute path of this node (calculated in the constructor) /// std::string m_Path; /// /// Saves the name of this node (set when read from backend) /// std::string m_Name; /// /// Saves the parent of this node /// Preferences* m_Parent; /// /// Saves the root of this tree /// Preferences* m_Root; /// /// Saves if something changed on this branch. /// Meaning that you would have to rewrite it. /// bool m_Dirty; /// /// Saves if this Node is removed (will not be saved to the backend). /// bool m_Removed; /// /// A storage to call the flush method. /// AbstractPreferencesStorage* m_Storage; /// /// A mutex to avoid concurrency crashes. Mutable because we need to use Mutex::lock() in const functions /// mutable Poco::Mutex m_Mutex; }; } namespace Base64 { /// /// Encode string to base64 (needed for writing byte arrays) /// std::string encode(const std::string &sString); /// /// Decode base64 to string (needed for reading byte arrays) /// std::string decode(const std::string &sString); }; /// /// Uses Preferences::ToString to print node information /// std::ostream& operator<<(std::ostream& os,const berry::Preferences& m); /// /// Uses Preferences::ToString to print node information /// std::ostream& operator<<(std::ostream& os,const berry::Preferences* m); #endif /* BERRYPREFERENCES_H_ */ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.cpp index 7876ac21a4..e4daf67af7 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.cpp @@ -1,204 +1,219 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryPreferencesService.h" #include "berryXMLPreferencesStorage.h" #include "Poco/ScopedLock.h" #include "Poco/DirectoryIterator.h" #include "berryPlatform.h" #include "Poco/DateTime.h" #include "Poco/DateTimeFormatter.h" using namespace std; bool berry::PreferencesService::IsA( const std::type_info& type ) const { std::string name(GetType().name()); return name == type.name() || Service::IsA(type); } const std::type_info& berry::PreferencesService::GetType() const { return typeid(berry::IPreferencesService); } std::string berry::PreferencesService::GetDefaultPreferencesDirPath() { string _PreferencesDirPath; _PreferencesDirPath = Platform::GetUserPath().toString() + ".BlueBerryPrefs"; return _PreferencesDirPath; } std::string berry::PreferencesService::GetDefaultPreferencesFileName() { return "prefs.xml"; } berry::PreferencesService::PreferencesService(string _PreferencesDir) : m_PreferencesDir(_PreferencesDir) { if(m_PreferencesDir.empty()) m_PreferencesDir = GetDefaultPreferencesDirPath(); Poco::File prefDir(m_PreferencesDir); if(!prefDir.exists()) prefDir.createDirectory(); Poco::DirectoryIterator dirIt(prefDir); Poco::File f; while(dirIt.path().getFileName() != "") { f = dirIt.path(); if(f.isFile()) { // check if this file is a preferences file string::size_type pos = dirIt.name().rfind(GetDefaultPreferencesFileName()); if(pos != string::npos) { string userName = dirIt.name().substr(0, pos); // set the storage to 0 (will be loaded later) m_PreferencesStorages[userName] = AbstractPreferencesStorage::Pointer(0); } } ++dirIt; } } berry::PreferencesService::~PreferencesService() { this->ShutDown(); } berry::IPreferences::Pointer berry::PreferencesService::GetSystemPreferences() { Poco::ScopedLock scopedMutex(m_Mutex); // sys prefs are indicated by an empty user string return this->GetUserPreferences(""); } berry::IPreferences::Pointer berry::PreferencesService::GetUserPreferences( std::string name ) { Poco::ScopedLock scopedMutex(m_Mutex); IPreferences::Pointer userPrefs(0); map::iterator it = m_PreferencesStorages.find(name); // does not exist or is not loaded yet if(it == m_PreferencesStorages.end() || it->second.IsNull()) { std::string path = m_PreferencesDir; if(name.empty()) path = path + Poco::Path::separator() + GetDefaultPreferencesFileName(); // else path = path + Poco::Path::separator() + name + GetDefaultPreferencesFileName(); XMLPreferencesStorage::Pointer storage(new XMLPreferencesStorage(path)); m_PreferencesStorages[name] = storage; } userPrefs = m_PreferencesStorages[name]->GetRoot(); return userPrefs; } std::vector berry::PreferencesService::GetUsers() const { Poco::ScopedLock scopedMutex(m_Mutex); vector users; for (map::const_iterator it = m_PreferencesStorages.begin() ; it != m_PreferencesStorages.end(); ++it) { users.push_back(it->first); } return users; } void berry::PreferencesService::ImportPreferences( Poco::File f, std::string name ) { map::iterator it = m_PreferencesStorages.find(name); if(it == m_PreferencesStorages.end() || it->second == 0) { this->GetUserPreferences(name); } //Poco::File defaultFile = it->second->GetFile(); XMLPreferencesStorage::Pointer storage(new XMLPreferencesStorage(f)); IPreferences::Pointer rootOfImportedPrefs = storage->GetRoot(); IPreferences::Pointer rootOfOldPrefs = m_PreferencesStorages[name]->GetRoot(); // make backup of old std::string exportFilePath = Poco::DateTimeFormatter::format(Poco::DateTime(), "%Y.%m.%d-%H%M%S"); exportFilePath = GetDefaultPreferencesDirPath() + Poco::Path::separator() + exportFilePath + "prefs.xml"; Poco::File exportFile(exportFilePath); this->ExportPreferences(exportFile, name); if(rootOfImportedPrefs.IsNotNull()) { this->ImportNode(rootOfImportedPrefs, rootOfOldPrefs); } } void berry::PreferencesService::ShutDown() { // flush all preferences for (map::const_iterator it = m_PreferencesStorages.begin() ; it != m_PreferencesStorages.end(); ++it) { // the preferences storage may be 0 if the corresponding file was never loaded if(it->second != 0) it->second->GetRoot()->Flush(); } } void berry::PreferencesService::ImportNode( IPreferences::Pointer nodeToImport , IPreferences::Pointer rootOfOldPrefs ) { //# overwrite properties IPreferences::Pointer oldNode = rootOfOldPrefs->Node(nodeToImport->AbsolutePath()); // get corresponding node in "old" tree std::vector keys = nodeToImport->Keys(); // get all keys for properties for (vector::const_iterator it = keys.begin() ; it != keys.end(); ++it) { oldNode->Put((*it), nodeToImport->Get((*it), ""));// set property in old node to the value of the imported. // properties not existing in imported are left untouched } // do it for all children vector childrenNames = nodeToImport->ChildrenNames(); for (vector::const_iterator it = childrenNames.begin() ; it != childrenNames.end(); ++it) { // with node->Node() you get the child node with the name this->ImportNode(nodeToImport->Node((*it)), rootOfOldPrefs); } } void berry::PreferencesService::ExportPreferences( Poco::File f, std::string name ) { map::iterator it = m_PreferencesStorages.find(name); if(it->second == 0) { this->GetUserPreferences(name); } Poco::File temp = it->second->GetFile(); it->second->SetFile(f); it->second->GetRoot()->Flush(); it->second->SetFile(temp); } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.h index f6618ce5b8..72422a37bc 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryPreferencesService.h @@ -1,103 +1,118 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYPREFERENCESSERVICE_H_ #define BERRYPREFERENCESSERVICE_H_ #include #include "berryIBerryPreferencesService.h" #include "berryAbstractPreferencesStorage.h" #include #include #include namespace berry { /** * Implementation of the IPreferencesService Interface */ class BERRY_RUNTIME PreferencesService : public QObject, public IBerryPreferencesService { Q_OBJECT Q_INTERFACES(berry::IPreferencesService) public: berryObjectMacro(PreferencesService) //# From berry::Service virtual bool IsA(const std::type_info& type) const; virtual const std::type_info& GetType() const; /// /// Returns the default name for the preferences data file /// static std::string GetDefaultPreferencesFileName(); /// /// Returns the path to the directory where all preference data is stored. /// static std::string GetDefaultPreferencesDirPath(); /// /// Reads in all users for which preferences exist. /// PreferencesService(std::string _PreferencesDir=""); /// /// Nothing to do here so far. /// virtual ~PreferencesService(); /** * If no system preference file exists create a new AbstractPreferencesStorage. * \see IPreferencesService::GetSystemPreferences() */ virtual IPreferences::Pointer GetSystemPreferences(); /** * If no user preference file exists create a new AbstractPreferencesStorage. * \see IPreferencesService::GetUserPreferences() */ virtual IPreferences::Pointer GetUserPreferences(std::string name); /** * \see IPreferencesService::GetUsers() */ virtual std::vector GetUsers() const; /// /// \see IPreferencesService::ImportPreferences() /// virtual void ImportPreferences(Poco::File f, std::string name=""); /// /// \see IPreferencesService::ExportPreferences() /// virtual void ExportPreferences(Poco::File f, std::string name=""); /// /// flushes all preferences /// virtual void ShutDown(); protected: /// /// Helper func for ImportPreferences(). Imports all nodes of an IPreferences tree recursively /// void ImportNode( IPreferences::Pointer nodeToImport , IPreferences::Pointer rootOfOldPrefs ); /// /// Holds the directory where the preferences files will be stored /// std::string m_PreferencesDir; /// /// Maps all user names to their preference storage. /// std::map m_PreferencesStorages; /// /// A mutex to avoid concurrency crashes. Mutable because we need to use Mutex::lock() in const functions /// mutable Poco::Mutex m_Mutex; }; } // namespace berry #endif /*BERRYPREFERENCESSERVICE_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp index 421edd4d8a..581fad5416 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.cpp @@ -1,173 +1,188 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryXMLPreferencesStorage.h" #include "berryPreferences.h" #include "berryLog.h" #define WARNMSG BERRY_WARN("XMLPreferencesStorage") #include "Poco/File.h" #include "Poco/DOM/DOMParser.h" #include "Poco/DOM/DOMWriter.h" #include "Poco/DOM/Element.h" #include "Poco/XML/XMLWriter.h" #include "Poco/DOM/Document.h" #include "Poco/DOM/NodeIterator.h" #include "Poco/DOM/NodeFilter.h" #include "Poco/DOM/AutoPtr.h" #include "Poco/SAX/InputSource.h" #include "Poco/DOM/NamedNodeMap.h" #include "Poco/DOM/NodeList.h" #include "Poco/DOM/Element.h" #include "Poco/Exception.h" #include "Poco/SAX/SAXException.h" using Poco::XML::DOMParser; using Poco::XML::InputSource; using Poco::XML::Document; using Poco::XML::NodeIterator; using Poco::XML::NodeFilter; using Poco::XML::Node; using Poco::XML::Element; using Poco::XML::AutoPtr; using Poco::Exception; #include #include namespace berry { XMLPreferencesStorage::XMLPreferencesStorage( const Poco::File& _File ) : AbstractPreferencesStorage(_File) { // file already exists try{ if(_File.exists()) { // build preferences tree from file InputSource src(_File.path()); DOMParser parser; AutoPtr pDoc = parser.parse(&src); this->ToPreferencesTree(pDoc->documentElement(), 0); } } catch (Poco::XML::SAXParseException& exc) { const std::string tempString = _File.path()+".backup"; BERRY_INFO << exc.what(); BERRY_INFO << "Preferences could not be loaded."; BERRY_INFO << "Creating " << tempString; BERRY_INFO << "and resetting to default values."; _File.copyTo(tempString); this->m_Root = NULL; } // if root is null make new one if(this->m_Root.IsNull()) { this->m_Root = Preferences::Pointer(new Preferences(Preferences::PropertyMap(), "", 0, this)); } } void XMLPreferencesStorage::Flush(IPreferences* /*_Preferences*/) throw(Poco::Exception, BackingStoreException) { try { this->ToDOMTree(dynamic_cast(this->m_Root.GetPointer()), 0); // flush dom to file Poco::XML::DOMWriter writer; //writer.setNewLine("\n"); writer.setOptions(Poco::XML::XMLWriter::PRETTY_PRINT); std::ofstream f; f.open (this->m_File.path().c_str()); // PRECISION setting // f.precision(10); writer.writeNode(f, m_Document); f.close(); } catch (std::exception& e) { WARNMSG << e.what(); } } XMLPreferencesStorage::~XMLPreferencesStorage() { } void XMLPreferencesStorage::ToPreferencesTree( Poco::XML::Node* DOMNode, Preferences* prefParentNode ) { // collect properties from attributes Preferences::PropertyMap properties; Poco::XML::Element* elem = dynamic_cast(DOMNode); std::string name = elem->getAttribute("name"); // create a new Preferences node Preferences::Pointer newNode(new Preferences(properties, name, prefParentNode, this)); // save the new Preferences node as root node if needed if(prefParentNode == 0) m_Root = newNode; // recursion: now go on for all child nodes of DOMNode Poco::XML::NodeList* childNodes = elem->childNodes(); Poco::XML::Node* currentNode = 0; Poco::XML::Element* prop = 0; std::string key; std::string value; for (unsigned int i = 0; i != childNodes->length(); ++i) { currentNode = childNodes->item(i); if(currentNode->nodeName() == "preferences") this->ToPreferencesTree(currentNode, newNode.GetPointer()); else if(currentNode->nodeName() == "property") { prop = dynamic_cast(currentNode); key = prop->getAttribute("name"); value = prop->getAttribute("value"); newNode->Put(key, value); } } } void XMLPreferencesStorage::ToDOMTree( Preferences* prefNode, Poco::XML::Node* parentDOMNode ) { if(parentDOMNode == 0) { m_Document = new Poco::XML::Document; parentDOMNode = m_Document; } //# create DOMNode from Preferences Element* newNode = m_Document->createElement("preferences"); newNode->setAttribute("name", prefNode->Name()); // make attributes Preferences::PropertyMap properties = prefNode->GetProperties(); for (Preferences::PropertyMap::iterator it = properties.begin() ; it != properties.end(); it++) { Element* newProp = m_Document->createElement("property"); newProp->setAttribute("name", it->first); newProp->setAttribute("value", it->second); newNode->appendChild(newProp); } // save in parentDOMNode parentDOMNode->appendChild(newNode); // recursion: now do that for all child Preferences nodes Preferences::ChildrenList children = prefNode->GetChildren(); for (Preferences::ChildrenList::iterator it = children.begin() ; it != children.end(); it++) { this->ToDOMTree((*it).GetPointer(), newNode); } } } diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.h b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.h index f775de4f37..249503aca2 100644 --- a/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.h +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/src/internal/berryXMLPreferencesStorage.h @@ -1,57 +1,72 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYXMLPREFERENCES_H_ #define BERRYXMLPREFERENCES_H_ #include #include "berryAbstractPreferencesStorage.h" #include "Poco/Path.h" #include "Poco/DOM/Node.h" #include "Poco/DOM/Document.h" #include "Poco/AutoPtr.h" namespace berry { class Preferences; /// /// Implementation of the OSGI Preferences Interface. /// Wraps a DOMNode. /// class BERRY_RUNTIME XMLPreferencesStorage: public AbstractPreferencesStorage { public: /// /// For use with berry::SmartPtr /// berryObjectMacro(berry::XMLPreferencesStorage) /// /// Construct a new XML-based PreferencesStorage /// XMLPreferencesStorage(const Poco::File& _File); /// /// To be implemented in the subclasses. /// virtual void Flush(IPreferences* _Preferences) throw(Poco::Exception, BackingStoreException); /// /// Nothing to do here /// virtual ~XMLPreferencesStorage(); protected: /// /// Construct Preferences tree from DOM tree (recursive) /// Construct a PreferencesNode from the DOMNode by using prefParentNode /// void ToPreferencesTree(Poco::XML::Node* DOMNode, Preferences* prefParentNode); /// /// Construct DOM tree from Preferences tree (recursive) /// Construct a DOMNode from the prefNode by using parentDOMNode /// void ToDOMTree(Preferences* prefNode, Poco::XML::Node* parentDOMNode); protected: Poco::AutoPtr m_Document; }; } #endif /* BERRYXMLPREFERENCES_H_ */ diff --git a/BlueBerry/Bundles/org.blueberry.osgi/src/berryStackTrace.cpp b/BlueBerry/Bundles/org.blueberry.osgi/src/berryStackTrace.cpp index 07545ef4e9..1b185c3476 100755 --- a/BlueBerry/Bundles/org.blueberry.osgi/src/berryStackTrace.cpp +++ b/BlueBerry/Bundles/org.blueberry.osgi/src/berryStackTrace.cpp @@ -1,789 +1,804 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /************************************************************************* * * $Id$ * * Copyright (c) 1998 by Bjorn Reese * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************ * * 1999/08/19 - breese * - Cleaned up the interface * * 1999/08/06 - breese * - Added U_STACK_TRACE for HP/UX * * 1999/01/24 - breese * - Added GCC_DumpStack * * 1998/12/21 - breese * - Fixed include files and arguments for waitpid() * - Made an AIX workaround for waitpid() exiting with EINTR * - Added a missing 'quit' command for OSF dbx * ************************************************************************/ #if defined(unix) || defined(__unix) || defined(__xlC__) # define PLATFORM_UNIX #elif defined(WIN32) || defined(_WIN32) # define PLATFORM_WIN32 #endif #if defined(_AIX) || defined(__xlC__) # define PLATFORM_AIX #elif defined(__FreeBSD__) # define PLATFORM_FREEBSD #elif defined(hpux) || defined(__hpux) || defined(_HPUX_SOURCE) # define PLATFORM_HPUX #elif defined(sgi) || defined(mips) || defined(_SGI_SOURCE) # define PLATFORM_IRIX #elif defined(__osf__) # define PLATFORM_OSF #elif defined(M_I386) || defined(_SCO_DS) || defined(_SCO_C_DIALECT) # define PLATFORM_SCO #elif defined(sun) || defined(__sun__) || defined(__SUNPRO_C) # if defined(__SVR4) || defined(__svr4__) # define PLATFORM_SOLARIS # endif #endif /* ANSI C includes */ #include #include #include #include #include #include #include #if defined(PLATFORM_UNIX) # include # include # include # if defined(PLATFORM_IRIX) && defined(USE_BUILTIN) /* Compile with -DUSE_BUILTIN and -lexc */ # include # elif defined(PLATFORM_HPUX) && defined(USE_BUILTIN) /* Compile with -DUSE_BUILTIN and -lcl */ extern void U_STACK_TRACE(void); # endif #endif #ifndef STDIN_FILENO # define STDIN_FILENO 0 # define STDOUT_FILENO 1 # define STDERR_FILENO 2 #endif // STDIN_FILENO #include "berryStackTrace.h" #ifndef FALSE # define FALSE (0 == 1) # define TRUE (! FALSE) #endif #define SYS_ERROR -1 #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #define MAX_BUFFER_SIZE 512 #if defined(__GNUC__) /* Change the code if ADDRESSLIST_SIZE is increased */ # define ADDRESSLIST_SIZE 20 #endif /************************************************************************* * Globals * * We cannot pass custom arguments to signal handlers so we store * them as global variables (but limit their scope to this file.) */ static const char *global_progname; static int global_output = STDOUT_FILENO; #if defined(PLATFORM_UNIX) /************************************************************************* * my_pclose [private] */ static void my_pclose(int fd, int pid) { close(fd); /* Make sure the the child process has terminated */ (void)kill(pid, SIGTERM); } /************************************************************************* * my_popen [private] */ static int my_popen(const char *command, pid_t *pid) { int rc; int pipefd[2]; rc = pipe(pipefd); if (SYS_ERROR != rc) { *pid = fork(); switch (*pid) { case SYS_ERROR: rc = SYS_ERROR; close(pipefd[0]); close(pipefd[1]); break; case 0: /* Child */ close(pipefd[0]); close(STDOUT_FILENO); close(STDERR_FILENO); dup2(pipefd[1], STDOUT_FILENO); dup2(pipefd[1], STDERR_FILENO); /* * The System() call assumes that /bin/sh is * always available, and so will we. */ execl("/bin/sh", "/bin/sh", "-c", command, NULL); _exit(EXIT_FAILURE); break; default: /* Parent */ close(pipefd[1]); rc = pipefd[0]; break; } /* switch */ } return rc; } /************************************************************************* * my_getline [private] */ static int my_getline(int fd, char *buffer, int max) { char c; int i = 0; do { if (read(fd, &c, 1) < 1) return 0; if (i < max) buffer[i++] = c; } while (c != '\n'); buffer[i] = (char)0; return i; } /************************************************************************* * GCC_DumpStack [private] * * * This code is still experimental. * * Stackbased arrays are used to prevent allocating from the heap. * Warning: sprintf/sscanf are not ASync safe. They were used for * convenience. * * 'nm' is used because it is most widespread * GNU: nm [-B] * Solaris: nm -x -p * IRIX: nm -x -B (but __builtin_return_address() always returns NULL) * AIX: nm -x -B * OSF/1: nm -B * SCO/OpenServer: nm -x -p * HP/UX nm -x -p */ #if defined(__GNUC__) && defined(USE_BUILTIN) typedef struct { unsigned long realAddress; unsigned long closestAddress; char name[MAX_BUFFER_SIZE + 1]; char type; } address_T; static void GCC_DumpStack(void) { int i; void *p = &p; /* dummy start value */ address_T syms[ADDRESSLIST_SIZE + 1]; char buffer[MAX_BUFFER_SIZE]; int fd; pid_t pid; unsigned long addr; unsigned long highestAddress; unsigned long lowestAddress; char type; char *pname; char name[MAX_BUFFER_SIZE]; int number; for (i = 0; p; i++) { /* * This is based on code by Steve Coleman * * __builtin_return_address() only accepts a constant as argument. */ switch (i) { case 0: if (__builtin_frame_address(0)) p = __builtin_return_address(0); else p = NULL; break; case 1: if (__builtin_frame_address(1)) p = __builtin_return_address(1); else p = NULL; break; case 2: if (__builtin_frame_address(2)) p = __builtin_return_address(2); else p = NULL; break; case 3: if (__builtin_frame_address(3)) p = __builtin_return_address(3); else p = NULL; break; case 4: if (__builtin_frame_address(4)) p = __builtin_return_address(4); else p = NULL; break; case 5: if (__builtin_frame_address(5)) p = __builtin_return_address(5); else p = NULL; break; case 6: if (__builtin_frame_address(6)) p = __builtin_return_address(6); else p = NULL; break; case 7: if (__builtin_frame_address(7)) p = __builtin_return_address(7); else p = NULL; break; case 8: if (__builtin_frame_address(8)) p = __builtin_return_address(8); else p = NULL; break; case 9: if (__builtin_frame_address(9)) p = __builtin_return_address(9); else p = NULL; break; case 10: if (__builtin_frame_address(10)) p = __builtin_return_address(10); else p = NULL; break; case 11: if (__builtin_frame_address(11)) p = __builtin_return_address(11); else p = NULL; break; case 12: if (__builtin_frame_address(12)) p = __builtin_return_address(12); else p = NULL; break; case 13: if (__builtin_frame_address(13)) p = __builtin_return_address(13); else p = NULL; break; case 14: if (__builtin_frame_address(14)) p = __builtin_return_address(14); else p = NULL; break; case 15: if (__builtin_frame_address(15)) p = __builtin_return_address(15); else p = NULL; break; case 16: if (__builtin_frame_address(16)) p = __builtin_return_address(16); else p = NULL; break; case 17: if (__builtin_frame_address(17)) p = __builtin_return_address(17); else p = NULL; break; case 18: if (__builtin_frame_address(18)) p = __builtin_return_address(18); else p = NULL; break; case 19: if (__builtin_frame_address(19)) p = __builtin_return_address(19); else p = NULL; break; default: /* Change ADDRESSLIST_SIZE if more are added */ p = NULL; break; } if ((p) && (i < ADDRESSLIST_SIZE)) { syms[i].realAddress = (unsigned long)p; syms[i].closestAddress = 0; syms[i].name[0] = (char)0; syms[i].type = ' '; } else { syms[i].realAddress = 0; break; /* for */ } } /* for */ /* First find out if we are using GNU or vendor nm */ number = 0; strcpy(buffer, "nm -V 2>/dev/null | grep GNU | wc -l"); fd = my_popen(buffer, &pid); if (SYS_ERROR != fd) { if (my_getline(fd, buffer, sizeof(buffer))) { sscanf(buffer, "%d", &number); } my_pclose(fd, pid); } if (number == 0) /* vendor nm */ { # if defined(PLATFORM_SOLARIS) || defined(PLATFORM_SCO) || defined(PLATFORM_HPUX) strcpy(buffer, "nm -x -p "); # elif defined(PLATFORM_AIX) || defined(PLATFORM_IRIX) || defined(PLATFORM_OSF) strcpy(buffer, "nm -x -B "); # else strcpy(buffer, "nm -B "); # endif } else /* GNU nm */ strcpy(buffer, "nm -B "); strcat(buffer, global_progname); lowestAddress = ULONG_MAX; highestAddress = 0; fd = my_popen(buffer, &pid); if (SYS_ERROR != fd) { while (my_getline(fd, buffer, sizeof(buffer))) { if (buffer[0] == '\n') continue; if (3 == sscanf(buffer, "%lx %c %s", &addr, &type, name)) { if ((type == 't') || type == 'T') { if (addr == 0) continue; /* while */ if (addr < lowestAddress) lowestAddress = addr; if (addr > highestAddress) highestAddress = addr; for (i = 0; syms[i].realAddress != 0; i++) { if ((addr <= syms[i].realAddress) && (addr > syms[i].closestAddress)) { syms[i].closestAddress = addr; strncpy(syms[i].name, name, MAX_BUFFER_SIZE); syms[i].name[MAX_BUFFER_SIZE] = (char)0; syms[i].type = type; } } } } } my_pclose(fd, pid); for (i = 0; syms[i].realAddress != 0; i++) { if ((syms[i].name[0] == (char)0) || (syms[i].realAddress <= lowestAddress) || (syms[i].realAddress >= highestAddress)) { sprintf(buffer, "[%d] 0x%08lx ???\n", i, syms[i].realAddress); } else { sprintf(buffer, "[%d] 0x%08lx <%s + 0x%lx> %c\n", i, syms[i].realAddress, syms[i].name, syms[i].realAddress - syms[i].closestAddress, syms[i].type); } write(global_output, buffer, strlen(buffer)); } } } #endif /************************************************************************* * DumpStack [private] */ static int DumpStack(char *format, ...) { int gotSomething = FALSE; int fd; pid_t pid; int status = EXIT_FAILURE; int rc; va_list args; char *buffer; char cmd[MAX_BUFFER_SIZE]; char buf[MAX_BUFFER_SIZE]; /* * Please note that vsprintf() is not ASync safe (ie. cannot safely * be used from a signal handler.) If this proves to be a problem * then the cmd string can be built by more basic functions such as * strcpy, strcat, and a homemade integer-to-ascii function. */ va_start(args, format); vsprintf(cmd, format, args); va_end(args); fd = my_popen(cmd, &pid); if (SYS_ERROR != fd) { /* * Wait for the child to exit. This must be done * to make the debugger attach successfully. * The output from the debugger is buffered on * the pipe. * * AIX needs the looping hack */ do { rc = waitpid(pid, &status, 0); } while ((SYS_ERROR == rc) && (EINTR == errno)); if ((WIFEXITED(status)) && (WEXITSTATUS(status) == EXIT_SUCCESS)) { while (my_getline(fd, buf, sizeof(buf))) { buffer = buf; if (! gotSomething) { size_t written = 0; written += write(global_output, "Output from ", strlen("Output from ")); strtok(cmd, " "); written += write(global_output, cmd, strlen(cmd)); written += write(global_output, "\n", strlen("\n")); if (written) gotSomething = TRUE; } if ('\n' == buf[strlen(buf)-1]) { buf[strlen(buf)-1] = (char)0; } size_t written = 0; written += write(global_output, buffer, strlen(buffer)); written += write(global_output, "\n", strlen("\n")); if (written != strlen(buffer) + strlen("\n")) { gotSomething = FALSE; } } } my_pclose(fd, pid); } return gotSomething; } #endif /* PLATFORM_UNIX */ /************************************************************************* * StackTrace */ void StackTrace(void) { #if defined(PLATFORM_UNIX) /* * In general dbx seems to do a better job than gdb. * * Different dbx implementations require different flags/commands. */ # if defined(PLATFORM_AIX) if (DumpStack("dbx -a %d 2>/dev/null </dev/null </dev/null <&1 </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null <&1 < < * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************ * * Purpose: * To generate a stacktrace of a program. * * Description: * If a debugger is located on the machine we will try this first, * as it usually give better information than built-in methods. * The debugger needs the name of the program to be able to attach * to it, so this must be passed to StackTraceInit(). The second * argument is a filedescriptor that StackTrace() writes to. If this * argument is -1 then standard output will be used. * * Compilation: * Some platforms have a built-in method to generate stacktraces, but * they are usually located in some non-standard library. The following * are supported: * * IRIX Compile with -DUSE_BUILTIN and -lexc * HP/UX Compile with -DUSE_BUILTIN and -lcl * GCC Compile with -DUSE_BUILTIN * ************************************************************************/ #ifndef H_DEBUG_STACKTRACE #define H_DEBUG_STACKTRACE void StackTrace(void); void StackTraceInit(const char *progname, int handle); #endif /* H_DEBUG_STACKTRACE */ diff --git a/BlueBerry/Bundles/org.blueberry.osgi/src/service/berryIExecutableExtension.h b/BlueBerry/Bundles/org.blueberry.osgi/src/service/berryIExecutableExtension.h index dfd849b9b5..a2d1b1b600 100644 --- a/BlueBerry/Bundles/org.blueberry.osgi/src/service/berryIExecutableExtension.h +++ b/BlueBerry/Bundles/org.blueberry.osgi/src/service/berryIExecutableExtension.h @@ -1,128 +1,143 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIEXECUTABLEEXTENSION_H_ #define BERRYIEXECUTABLEEXTENSION_H_ #include "berryObject.h" #include "berrySmartPointer.h" #include namespace berry { struct IConfigurationElement; /** * Interface for executable extension classes that require access to * their configuration element, or implement an extension adapter. *

* Extension adapters are typically required in cases where the extension * implementation does not follow the interface rules specified * by the provider of the extension point. In these * cases, the role of the adapter is to map between the extension point * interface, and the actual extension implementation. In general, adapters * are used when attempting to plug-in existing Java implementations, or * non-Java implementations (e.g., external executables). *

*

* Clients may implement this interface. *

* * @see IConfigurationElement#createExecutableExtension * @since 3.0 */ struct IExecutableExtension { /** * This method is called by the implementation of the method * IConfigurationElement.createExecutableExtension * on a newly constructed extension, passing it its relevant configuration * information. Most executable extensions only make use of the first * two call arguments. *

* Regular executable extensions specify their Java implementation * class name as an attribute of the configuration element for the * extension. For example *

    *     <action run="com.example.BaseAction"/>
    * 
* In the above example, this method would be called with a reference * to the <action> element (first argument), and * "run" as the name of the attribute that defined * this executable extension (second argument). *

*

* The last parameter is for the specific use of extension adapters * and is typically not used by regular executable extensions. *

*

* There are two supported ways of associating additional * adapter-specific data with the configuration in a way that * is transparent to the extension point implementor: *

*

* (1) by specifying adapter data as part of the implementation * class attribute value. The Java class name can be followed * by a ":" separator, followed by any adapter data in string * form. For example, if the extension point specifies an attribute * "run" to contain the name of the extension implementation, * an adapter can be configured as *

    *     <action run="com.example.ExternalAdapter:./cmds/util.exe -opt 3"/>
    * 
*

*

* (2) by converting the attribute used to specify the executable * extension to a child element of the original configuration element, * and specifying the adapter data in the form of xml markup. * Using this form, the example above would become *

    *     <action>
    *         <run class="com.xyz.ExternalAdapter">
    *             <parameter name="exec" value="./cmds/util.exe"/>
    *             <parameter name="opt"  value="3"/>
    *         </run>
    *     </action>
    * 
*

*

* Form (2) will typically only be * used for extension points that anticipate the majority of * extensions configured into it will in fact be in the form * of adapters. *

*

* In either case, the specified adapter class is instantiated using its * 0-argument public constructor. The adapter data is passed as the * last argument of this method. The data argument is defined as Object. * It can have the following values: *

    *
  • null, if no adapter data was supplied
  • *
  • in case (1), the initialization data * string is passed as a String
  • *
  • in case (2), the initialization data is passed * as a Hashtable containing the actual * parameter names and values (both Strings)
  • *
*

* * @param config the configuration element used to trigger this execution. * It can be queried by the executable extension for specific * configuration properties * @param propertyName the name of an attribute of the configuration element * used on the createExecutableExtension(String) call. This * argument can be used in the cases where a single configuration element * is used to define multiple executable extensions. * @param data adapter data in the form of a String, * a Hashtable, or null. * @exception CoreException if error(s) detected during initialization processing * @see IConfigurationElement#createExecutableExtension */ virtual void SetInitializationData(SmartPointer config, const std::string& propertyName, Object::Pointer data) = 0; virtual ~IExecutableExtension() {}; }; } Q_DECLARE_INTERFACE(berry::IExecutableExtension, "org.blueberry.IExecutableExtension") #endif /*BERRYIEXECUTABLEEXTENSION_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.cpp b/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.cpp index 400f66e4a8..40cc379e43 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.cpp +++ b/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.cpp @@ -1,23 +1,38 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryIWorkbenchPartConstants.h" namespace berry { const std::string IWorkbenchPartConstants::INTEGER_PROPERTY = "org.blueberry.ui.integerproperty"; const int IWorkbenchPartConstants::PROP_TITLE = 0x001; const int IWorkbenchPartConstants::PROP_DIRTY = 0x101; const int IWorkbenchPartConstants::PROP_INPUT = 0x102; const int IWorkbenchPartConstants::PROP_PART_NAME = 0x104; const int IWorkbenchPartConstants::PROP_CONTENT_DESCRIPTION = 0x105; const int IWorkbenchPartConstants::PROP_PREFERRED_SIZE = 0x303; const int IWorkbenchPartConstants::PROP_OPENED = 0x211; const int IWorkbenchPartConstants::PROP_CLOSED = 0x212; const int IWorkbenchPartConstants::PROP_PINNED = 0x213; const int IWorkbenchPartConstants::PROP_VISIBLE = 0x214; // const int IWorkbenchPartConstants::PROP_ZOOMED = 0x215; const int IWorkbenchPartConstants::PROP_ACTIVE_CHILD_CHANGED = 0x216; // const int IWorkbenchPartConstants::PROP_MAXIMIZED = 0x217; } diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.h b/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.h index 98ff5dbbbf..89a29a790d 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.h +++ b/BlueBerry/Bundles/org.blueberry.ui/src/berryIWorkbenchPartConstants.h @@ -1,101 +1,116 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYIWORKBENCHPARTCONSTANTS_H_ #define BERRYIWORKBENCHPARTCONSTANTS_H_ #include #include namespace berry { /** * This interface describes the constants used for IWorkbenchPart properties. *

* Note:This interface should not be implemented or extended. *

* * @since 3.0 * @noimplement This interface is not intended to be implemented by clients. */ struct BERRY_UI IWorkbenchPartConstants { /** * Used in a PropertyChangeEvent as the property string to signal * that integer flags are used. */ static const std::string INTEGER_PROPERTY; /** * The property id for getTitle, getTitleImage * and getTitleToolTip. */ static const int PROP_TITLE; /** * The property id for ISaveablePart.isDirty(). */ static const int PROP_DIRTY; /** * The property id for IEditorPart.getEditorInput(). */ static const int PROP_INPUT; /** * The property id for IWorkbenchPart2.getPartName */ static const int PROP_PART_NAME; /** * The property id for IWorkbenchPart2.getContentDescription() */ static const int PROP_CONTENT_DESCRIPTION; /** * The property id for any method on the optional ISizeProvider interface * @since 3.4 */ static const int PROP_PREFERRED_SIZE; /** * Indicates that the underlying part was created */ static const int PROP_OPENED; // = 0x211; /** * Internal property ID: Indicates that the underlying part was destroyed */ static const int PROP_CLOSED; // = 0x212; /** * Internal property ID: Indicates that the result of IEditorReference.isPinned() */ static const int PROP_PINNED; // = 0x213; /** * Internal property ID: Indicates that the result of getVisible() has changed */ static const int PROP_VISIBLE; // = 0x214; /** * Internal property ID: Indicates that the result of isZoomed() has changed */ //static const int PROP_ZOOMED = 0x215; /** * Internal property ID: Indicates that the part has an active child and the * active child has changed. (fired by PartStack) */ static const int PROP_ACTIVE_CHILD_CHANGED; // = 0x216; /** * Internal property ID: Indicates that changed in the min / max * state has changed */ //static final int PROP_MAXIMIZED = 0x217; }; } #endif /*BERRYIWORKBENCHPARTCONSTANTS_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/berrySelectionChangedEvent.h b/BlueBerry/Bundles/org.blueberry.ui/src/berrySelectionChangedEvent.h index 81fea4a5dc..78805927c5 100755 --- a/BlueBerry/Bundles/org.blueberry.ui/src/berrySelectionChangedEvent.h +++ b/BlueBerry/Bundles/org.blueberry.ui/src/berrySelectionChangedEvent.h @@ -1,67 +1,82 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYSELECTIONCHANGEDEVENT_H_ #define BERRYSELECTIONCHANGEDEVENT_H_ #include "berryISelection.h" namespace berry { struct ISelectionProvider; /** * \ingroup org_blueberry_ui * * Event object describing a selection change. The source of these * events is a selection provider. * * @see ISelection * @see ISelectionProvider * @see ISelectionChangedListener */ class BERRY_UI SelectionChangedEvent : public Object { public: berryObjectMacro(SelectionChangedEvent); /** * Creates a new event for the given source and selection. * * @param source the selection provider * @param selection the selection */ SelectionChangedEvent(SmartPointer source, ISelection::ConstPointer selection); SmartPointer GetSource() const; /** * Returns the selection. * * @return the selection */ ISelection::ConstPointer GetSelection() const; /** * Returns the selection provider that is the source of this event. * * @return the originating selection provider */ SmartPointer GetSelectionProvider() const; protected: /** * The selection. */ ISelection::ConstPointer selection; private: SmartPointer source; }; } #endif /*BERRYSELECTIONCHANGEDEVENT_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.cpp b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.cpp index 58f4a48d07..65a7419a8f 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.cpp +++ b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.cpp @@ -1,352 +1,367 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryPartList.h" #include "berrySaveablesList.h" #include "berryPartPane.h" #include "berryIWorkbenchPartConstants.h" #include "berryIWorkbenchPartSite.h" #include namespace berry { void PartList::PropertyChange(Object::Pointer source, int propId) { WorkbenchPartReference::Pointer ref = source.Cast< WorkbenchPartReference> (); if (propId == IWorkbenchPartConstants::PROP_OPENED) { this->PartOpened(ref); } else if (propId == IWorkbenchPartConstants::PROP_CLOSED) { this->PartClosed(ref); } else if (propId == IWorkbenchPartConstants::PROP_VISIBLE) { if (ref->GetVisible()) { this->PartVisible(ref); } else { this->PartHidden(ref); } } else if (propId == IWorkbenchPartConstants::PROP_INPUT) { this->PartInputChanged(ref); } } IWorkbenchPartReference::Pointer PartList::GetActivePartReference() { return activePartReference.Lock(); } IEditorReference::Pointer PartList::GetActiveEditorReference() { return activeEditorReference.Lock(); } IEditorPart::Pointer PartList::GetActiveEditor() { return activeEditorReference.Expired() ? IEditorPart::Pointer(0) : activeEditorReference.Lock()->GetEditor( false); } IWorkbenchPart::Pointer PartList::GetActivePart() { return activePartReference.Expired() ? IWorkbenchPart::Pointer(0) : activePartReference.Lock()->GetPart(false); } //std::vector PartList::GetEditors() //{ // std::vector result; // for (std::deque::iterator iter = // parts.begin(); iter != parts.end(); ++iter) // { // if (iter->Cast () != 0) // result.push_back(iter->Cast ()); // } // // return result; //} void PartList::AddPart(WorkbenchPartReference::Pointer ref) { poco_assert(ref.IsNotNull()); ref->AddPropertyListener(IPropertyChangeListener::Pointer(this)); // if (!this->Contains(ref)) // { // parts.push_back(ref); // } // parts.add(ref); this->FirePartAdded(ref); // If this part is already open, fire the "part opened" event // immediately if (ref->GetPart(false).IsNotNull()) { this->PartOpened(ref); } // If this part is already visible, fire the visibility event // immediately if (ref->GetVisible()) { this->PartVisible(ref); } } void PartList::SetActivePart(IWorkbenchPartReference::Pointer ref) { if (activePartReference.Lock() == ref) { return; } IWorkbenchPartReference::Pointer oldPart = activePartReference.Lock(); // A part can't be activated until it is added //poco_assert(ref == 0 || this->Contains(ref)); //std::remove(parts.begin(), parts.end(), ref); //parts.push_front(ref); activePartReference = ref; this->FireActivePartChanged(oldPart, ref); } void PartList::SetActiveEditor(IEditorReference::Pointer ref) { if (activeEditorReference.Lock() == ref) { return; } // A part can't be activated until it is added //poco_assert(ref == 0 || this->Contains(ref)); activeEditorReference = ref; //std::remove(parts.begin(), parts.end(), ref); //parts.push_front(ref); this->FireActiveEditorChanged(ref); } void PartList::RemovePart(WorkbenchPartReference::Pointer ref) { poco_assert(ref.IsNotNull()); // It is an error to remove a part that isn't in the list //poco_assert(this->Contains(ref)); // We're not allowed to remove the active part. We must deactivate it // first. poco_assert(activePartReference.Lock() != ref); // We're not allowed to remove the active editor. We must deactivate it // first. if (ref.Cast()) { poco_assert(activeEditorReference.Lock() != ref.Cast()); } if (ref->GetVisible()) { ref->SetVisible(false); } // If this part is currently open, fire the "part closed" event before // removal if (ref->GetPart(false).IsNotNull()) { this->PartClosed(ref); } //std::remove(parts.begin(), parts.end(), ref); ref->RemovePropertyListener(IPropertyChangeListener::Pointer(this)); this->FirePartRemoved(ref); } //int PartList::IndexOf(const IWorkbenchPartReference::Pointer ref) const //{ // std::deque::const_iterator result = std::find(parts.begin(), parts.end(), ref); // if (result == parts.end()) return -1; // else return result - parts.begin(); //} //void PartList::BringToTop(IWorkbenchPartReference::Pointer ref) //{ // IStackableContainer::Pointer targetContainer; // if (ref != 0) // { // PartPane::Pointer pane = ref.Cast()->GetPane(); // if (pane != 0) // { // targetContainer = pane->GetContainer(); // } // } // // std::deque::iterator newIndex = this->LastIndexOfContainer(targetContainer); // // // //New index can be -1 if there is no last index // // if (newIndex >= 0 && ref == parts.get(newIndex)) // // return; // // std::remove(parts.begin(), parts.end(), ref); // if(newIndex != parts.end()) // { // parts.insert(newIndex, ref); // } // else // parts.push_front(ref); //} //std::vector //PartList::GetParts(const std::vector& views) //{ // std::vector resultList; // for (std::deque::iterator partIter = parts.begin(); // partIter != parts.end(); ++partIter) // { // IWorkbenchPartReference::Pointer ref = *partIter; // if (ref.Cast() != 0) // { // //Filter views from other perspectives // for (unsigned int i = 0; i < views.size(); i++) // { // if (ref == views[i]) // { // resultList.push_back(ref); // break; // } // } // } // else // { // resultList.push_back(ref); // } // } // return resultList; //} //std::deque::iterator //PartList::LastIndexOfContainer(IStackableContainer::Pointer container) //{ // for (std::deque::iterator iter = parts.begin(); // iter != parts.end(); ++iter) // { // IWorkbenchPartReference::Pointer ref = *iter; // // IStackableContainer::Pointer cnt; // PartPane::Pointer pane = ref.Cast()->GetPane(); // if (pane != 0) // { // cnt = pane->GetContainer(); // } // if (cnt == container) // { // return iter; // } // } // // return parts.end(); //} //bool PartList::Contains(IWorkbenchPartReference::Pointer ref) //{ // return std::find(parts.begin(), parts.end(), ref) != parts.end(); //} void PartList::PartInputChanged(WorkbenchPartReference::Pointer ref) { this->FirePartInputChanged(ref); } void PartList::PartHidden(WorkbenchPartReference::Pointer ref) { // Part should not be null poco_assert(ref.IsNotNull()); // This event should only be fired if the part is actually visible poco_assert(!ref->GetVisible()); // We shouldn't be receiving events from parts until they are in the // list //poco_assert(this->Contains(ref)); this->FirePartHidden(ref); } void PartList::PartOpened(WorkbenchPartReference::Pointer ref) { poco_assert(ref.IsNotNull()); IWorkbenchPart::Pointer actualPart = ref->GetPart(false); // We're firing the event that says "the part was just created"... so // there better be a part there. poco_assert(actualPart.IsNotNull()); // Must be called after the part is inserted into the part list //poco_assert(this->Contains(ref)); // The active part must be opened before it is activated, so we should // never get an open event for a part that is already active. // (This either indicates that a redundant // open event was fired or that a closed part was somehow activated) poco_assert(activePartReference.Lock() != ref); // The active editor must be opened before it is activated, so we should // never get an open event for an editor that is already active. // (This either indicates that a redundant // open event was fired or that a closed editor was somehow activated) poco_assert((void*)activeEditorReference.Lock().GetPointer() != (void*)ref.GetPointer()); SaveablesList::Pointer modelManager = actualPart ->GetSite()->GetService(ISaveablesLifecycleListener::GetManifestName()).Cast(); modelManager->PostOpen(actualPart); // Fire the "part opened" event this->FirePartOpened(ref); } void PartList::PartClosed(WorkbenchPartReference::Pointer ref) { poco_assert(ref.IsNotNull()); IWorkbenchPart::Pointer actualPart = ref->GetPart(false); // Called before the part is disposed, so the part should still be // there. poco_assert(actualPart.IsNotNull()); // Must be called before the part is actually removed from the part list // poco_assert(this->Contains(ref)); // Not allowed to close the active part. The part must be deactivated // before it may be closed. poco_assert(activePartReference.Lock() != ref); // Not allowed to close the active editor. The editor must be // deactivated before it may be closed. if (ref.Cast()) { poco_assert(activeEditorReference.Lock() != ref.Cast()); } this->FirePartClosed(ref); } void PartList::PartVisible(WorkbenchPartReference::Pointer ref) { // Part should not be null poco_assert(ref.IsNotNull()); // This event should only be fired if the part is actually visible poco_assert(ref->GetVisible()); // We shouldn't be receiving events from parts until they are in the // list //poco_assert(this->Contains(ref)); // Part must be open before it can be made visible poco_assert(ref->GetPart(false).IsNotNull()); this->FirePartVisible(ref); } } diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.h b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.h index 3dd9ab2a9f..81dc477dcc 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.h +++ b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartList.h @@ -1,174 +1,189 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYPARTLIST_H_ #define BERRYPARTLIST_H_ #include "berryWorkbenchPartReference.h" #include "berryIStackableContainer.h" #include "berryIEditorReference.h" #include "berryIViewReference.h" #include namespace berry { class PartList : public IPropertyChangeListener { private: // list of parts in the activation order (oldest last) //std::deque parts; IWorkbenchPartReference::WeakPtr activePartReference; IEditorReference::WeakPtr activeEditorReference; public: void PropertyChange(Object::Pointer source, int propId); IWorkbenchPartReference::Pointer GetActivePartReference(); IEditorReference::Pointer GetActiveEditorReference(); IEditorPart::Pointer GetActiveEditor(); IWorkbenchPart::Pointer GetActivePart(); //std::vector GetEditors(); void AddPart(WorkbenchPartReference::Pointer ref); /** * Sets the active part. * * @param ref */ void SetActivePart(IWorkbenchPartReference::Pointer ref); void SetActiveEditor(IEditorReference::Pointer ref); /** * In order to remove a part, it must first be deactivated. */ void RemovePart(WorkbenchPartReference::Pointer ref); //int IndexOf(const IWorkbenchPartReference::Pointer ref) const; /* * Ensures that the given part appears AFTER any other part in the same * container. */ //void BringToTop(IWorkbenchPartReference::Pointer ref); /* * Return a list with all parts (editors and views). */ //std::vector GetParts(const std::vector& views); private: /* * Returns the last (most recent) index of the given container in the activation list, or returns * -1 if the given container does not appear in the activation list. */ //std::deque::iterator // LastIndexOfContainer(IStackableContainer::Pointer container); void PartInputChanged(WorkbenchPartReference::Pointer ref); void PartHidden(WorkbenchPartReference::Pointer ref); void PartOpened(WorkbenchPartReference::Pointer ref); /** * Called when a concrete part is about to be destroyed. This is called * BEFORE disposal happens, so the part should still be accessable from the * part reference. * * @param ref */ void PartClosed(WorkbenchPartReference::Pointer ref); void PartVisible(WorkbenchPartReference::Pointer ref); //bool Contains(IWorkbenchPartReference::Pointer ref); protected: /** * Fire the event indicating that a part reference was just realized. That * is, the concrete IWorkbenchPart has been attached to the part reference. * * @param part * the reference that was create */ virtual void FirePartOpened(IWorkbenchPartReference::Pointer part) = 0; /** * Fire the event indicating that a part reference was just realized. That * is, the concrete IWorkbenchPart has been attached to the part reference. * * @param part * the reference that was create */ virtual void FirePartClosed(IWorkbenchPartReference::Pointer part) = 0; /** * Indicates that a new part reference was added to the list. * * @param part */ virtual void FirePartAdded(IWorkbenchPartReference::Pointer part) = 0; /** * Indicates that a part reference was removed from the list * * @param part */ virtual void FirePartRemoved(IWorkbenchPartReference::Pointer part) = 0; /** * Indicates that the active editor changed * * @param part * active part reference or null if none */ virtual void FireActiveEditorChanged(IWorkbenchPartReference::Pointer ref) = 0; /** * Indicates that the active part has changed * * @param part * active part reference or null if none */ virtual void FireActivePartChanged( IWorkbenchPartReference::Pointer oldPart, IWorkbenchPartReference::Pointer newPart) = 0; /** * Indicates that the part has been made visible * * @param ref */ virtual void FirePartVisible(IWorkbenchPartReference::Pointer ref) = 0; /** * Indicates that the part has been hidden * * @param ref */ virtual void FirePartHidden(IWorkbenchPartReference::Pointer ref) = 0; /** * Indicates that the part input has changed * * @param ref */ virtual void FirePartInputChanged(IWorkbenchPartReference::Pointer ref) = 0; virtual void FirePartBroughtToTop(IWorkbenchPartReference::Pointer ref) = 0; }; } #endif /*BERRYPARTLIST_H_*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.cpp b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.cpp index 4773d5c048..29676af242 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.cpp +++ b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.cpp @@ -1,123 +1,138 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "berryPartService.h" namespace berry { void PartService::FirePartActivated(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_ACTIVATED); // listeners2.firePartActivated(ref); partEvents.partActivated(ref); } /** * @param ref */ void PartService::FirePartDeactivated(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_DEACTIVATED); // listeners2.firePartDeactivated(ref); partEvents.partDeactivated(ref); } PartService::PartService(const std::string& debugListenersKey, const std::string& debugListeners2Key) { this->debugListeners2Key = debugListeners2Key; this->debugListenersKey = debugListenersKey; } void PartService::AddPartListener(IPartListener::Pointer l) { partEvents.AddListener(l); } void PartService::RemovePartListener(IPartListener::Pointer l) { partEvents.RemoveListener(l); } void PartService::FirePartBroughtToTop(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_BROUGHT_TO_TOP); // listeners2.firePartBroughtToTop(ref); partEvents.partBroughtToTop(ref); } void PartService::FirePartClosed(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_CLOSED); // listeners2.firePartClosed(ref); partEvents.partClosed(ref); } void PartService::FirePartVisible(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_VISIBLE); // listeners2.firePartVisible(ref); partEvents.partVisible(ref); } void PartService::FirePartHidden(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_HIDDEN); // listeners2.firePartHidden(ref); partEvents.partHidden(ref); } void PartService::FirePartInputChanged(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_INPUT_CHANGED); // listeners2.firePartInputChanged(ref); partEvents.partInputChanged(ref); } void PartService::FirePartOpened(IWorkbenchPartReference::Pointer ref) { // UIListenerLogging.logPartListener2Event(debugListeners2Key, this, ref, // UIListenerLogging.PE2_PART_OPENED); // listeners2.firePartOpened(ref); partEvents.partOpened(ref); } IWorkbenchPart::Pointer PartService::GetActivePart() { return activePart.Expired() ? IWorkbenchPart::Pointer(0) : activePart.Lock()->GetPart(false); } IWorkbenchPartReference::Pointer PartService::GetActivePartReference() { return activePart.Lock(); } void PartService::SetActivePart(IWorkbenchPartReference::Pointer ref) { IWorkbenchPartReference::Pointer oldRef = activePart.Lock(); // Filter out redundant activation events if (oldRef == ref) { return; } if (oldRef.IsNotNull()) { this->FirePartDeactivated(oldRef); } activePart = ref; if (ref.IsNotNull()) { this->FirePartActivated(ref); } } } diff --git a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.h b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.h index 083d12292f..55538e0ea8 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.h +++ b/BlueBerry/Bundles/org.blueberry.ui/src/internal/berryPartService.h @@ -1,82 +1,97 @@ +/*=================================================================== + +BlueBerry Platform + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef BERRYPARTSERVICE_H_ #define BERRYPARTSERVICE_H_ #include "berryIPartService.h" #include namespace berry { class PartService : public IPartService { private: //PartListenerList listeners = new PartListenerList(); IPartListener::Events partEvents; IWorkbenchPartReference::WeakPtr activePart; std::string debugListenersKey; std::string debugListeners2Key; /** * @param ref */ void FirePartActivated(IWorkbenchPartReference::Pointer ref); /** * @param ref */ void FirePartDeactivated(IWorkbenchPartReference::Pointer ref); public: PartService(const std::string& debugListenersKey, const std::string& debugListeners2Key); /* * (non-Javadoc) * Method declared on IPartService */ void AddPartListener(IPartListener::Pointer l); /* * (non-Javadoc) * Method declared on IPartService */ void RemovePartListener(IPartListener::Pointer l); /** * @param ref */ void FirePartBroughtToTop(IWorkbenchPartReference::Pointer ref); /** * @param ref */ void FirePartClosed(IWorkbenchPartReference::Pointer ref); void FirePartVisible(IWorkbenchPartReference::Pointer ref); void FirePartHidden(IWorkbenchPartReference::Pointer ref); void FirePartInputChanged(IWorkbenchPartReference::Pointer ref); /** * @param ref */ void FirePartOpened(IWorkbenchPartReference::Pointer ref); IWorkbenchPart::Pointer GetActivePart(); IWorkbenchPartReference::Pointer GetActivePartReference(); void SetActivePart(IWorkbenchPartReference::Pointer ref); }; } #endif /*BERRYPARTSERVICE_H_*/ diff --git a/CMake/mitkMacroCreateModule.cmake b/CMake/mitkMacroCreateModule.cmake index 3dde58f5f8..877328eb64 100644 --- a/CMake/mitkMacroCreateModule.cmake +++ b/CMake/mitkMacroCreateModule.cmake @@ -1,303 +1,318 @@ ################################################################## # # MITK_CREATE_MODULE # #! Creates a module for the automatic module dependency system within MITK. #! Configurations are generated in the moduleConf directory. #! #! USAGE: #! #! \code #! MITK_CREATE_MODULE( #! [INCLUDE_DIRS ] #! [INTERNAL_INCLUDE_DIRS ] #! [DEPENDS ] #! [PACKAGE_DEPENDS ] #! [TARGET_DEPENDS #! [EXPORT_DEFINE ] #! [QT_MODULE] #! [HEADERS_ONLY] #! [WARNINGS_AS_ERRORS] #! \endcode #! #! \param MODULE_NAME_IN The name for the new module #! \param HEADERS_ONLY specify this if the modules just contains header files. ################################################################## macro(MITK_CREATE_MODULE MODULE_NAME_IN) MACRO_PARSE_ARGUMENTS(MODULE "SUBPROJECTS;VERSION;INCLUDE_DIRS;INTERNAL_INCLUDE_DIRS;DEPENDS;DEPENDS_INTERNAL;PACKAGE_DEPENDS;TARGET_DEPENDS;EXPORT_DEFINE;ADDITIONAL_LIBS;GENERATED_CPP" "QT_MODULE;FORCE_STATIC;HEADERS_ONLY;GCC_DEFAULT_VISIBILITY;NO_INIT;WARNINGS_AS_ERRORS" ${ARGN}) set(MODULE_NAME ${MODULE_NAME_IN}) if(MODULE_HEADERS_ONLY) set(MODULE_PROVIDES ) else() set(MODULE_PROVIDES ${MODULE_NAME}) if(NOT MODULE_NO_INIT AND NOT MODULE_NAME STREQUAL "Mitk") # Add a dependency to the "Mitk" module list(APPEND MODULE_DEPENDS Mitk) endif() endif() if(NOT MODULE_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) endif() endif() # check if the subprojects exist as targets if(MODULE_SUBPROJECTS) foreach(subproject ${MODULE_SUBPROJECTS}) if(NOT TARGET ${subproject}) message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target") endif() endforeach() endif() # assume worst case set(MODULE_IS_ENABLED 0) # first we check if we have an explicit module build list if(MITK_MODULES_TO_BUILD) list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX) if(_MOD_INDEX EQUAL -1) set(MODULE_IS_EXCLUDED 1) endif() endif() if(NOT MODULE_IS_EXCLUDED) # first of all we check for the dependencies MITK_CHECK_MODULE(_MISSING_DEP ${MODULE_DEPENDS}) if(_MISSING_DEP) message("Module ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") set(MODULE_IS_ENABLED 0) else(_MISSING_DEP) set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${MODULE_PACKAGE_DEPENDS}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("Module ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) endif() endforeach() if(MODULE_IS_ENABLED) if(NOT MODULE_QT_MODULE OR MITK_USE_QT) set(MODULE_IS_ENABLED 1) _MITK_CREATE_MODULE_CONF() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif(NOT MODULE_EXPORT_DEFINE) if(MITK_GENERATE_MODULE_DOT) message("MODULEDOTNAME ${MODULE_NAME}") foreach(dep ${MODULE_DEPENDS}) message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ") endforeach(dep) endif(MITK_GENERATE_MODULE_DOT) if(NOT MODULE_NO_INIT) set(MODULE_LIBNAME ${MODULE_PROVIDES}) set(module_init_src_file) usFunctionGenerateModuleInit(module_init_src_file NAME ${MODULE_NAME} LIBRARY_NAME ${MODULE_LIBNAME} DEPENDS ${MODULE_DEPENDS} ${MODULE_DEPENDS_INTERNAL} ${MODULE_PACKAGE_DEPENDS} #VERSION ${MODULE_VERSION} ) endif() set(DEPENDS "${MODULE_DEPENDS}") set(DEPENDS_BEFORE "not initialized") set(PACKAGE_DEPENDS "${MODULE_PACKAGE_DEPENDS}") MITK_USE_MODULE("${MODULE_DEPENDS}") # ok, now create the module itself include_directories(. ${ALL_INCLUDE_DIRECTORIES}) include(files.cmake) set(module_compile_flags ) if(WIN32) set(module_compile_flags "${module_compile_flags} -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") endif() if(MODULE_GCC_DEFAULT_VISIBILITY) set(use_visibility_flags 0) else() # We only support hidden visibility for gcc for now. Clang 3.0 still has troubles with # correctly marking template declarations and explicit template instantiations as exported. # See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028 # and http://llvm.org/bugs/show_bug.cgi?id=10113 if(CMAKE_COMPILER_IS_GNUCXX) set(use_visibility_flags 1) else() # set(use_visibility_flags 0) endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) # MinGW does not export all symbols automatically, so no need to set flags. # # With gcc < 4.5, RTTI symbols from classes declared in third-party libraries # which are not "gcc visibility aware" are marked with hidden visibility in # DSOs which include the class declaration and which are compiled with # hidden visibility. This leads to dynamic_cast and exception handling problems. # While this problem could be worked around by sandwiching the include # directives for the third-party headers between "#pragma visibility push/pop" # statements, it is generally safer to just use default visibility with # gcc < 4.5. if(${GCC_VERSION} VERSION_LESS "4.5" OR MINGW) set(use_visibility_flags 0) endif() endif() if(use_visibility_flags) mitkFunctionCheckCompilerFlags("-fvisibility=hidden" module_compile_flags) mitkFunctionCheckCompilerFlags("-fvisibility-inlines-hidden" module_compile_flags) endif() configure_file(${MITK_SOURCE_DIR}/CMake/moduleExports.h.in ${CMAKE_BINARY_DIR}/${MODULES_CONF_DIRNAME}/${MODULE_NAME}Exports.h @ONLY) if(MODULE_WARNINGS_AS_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCompilerFlags("/WX" module_compile_flags) else() mitkFunctionCheckCompilerFlags("-Werror" module_compile_flags) - mitkFunctionCheckCompilerFlags("-Wno-c++0x-static-nonintegral-init" module_compile_flags) - mitkFunctionCheckCompilerFlags("-Wno-gnu" module_compile_flags) + + # The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang + # versions to "static-member-init", see + # http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html + # + # Also, older Clang and seemingly all gcc versions do not warn if unknown + # "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the + # command line. This may get confusing if unrelated compiler errors happen and + # the error output then additinally contains errors about unknown flags (which + # is not the case if there were no compile errors). + # + # So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by + # the compiler and if applicable, prints the specific warning as a real warning and + # not as an error (although -Werror was given). + + mitkFunctionCheckCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_compile_flags) + mitkFunctionCheckCompilerFlags("-Wno-error=gnu" module_compile_flags) endif() endif(MODULE_WARNINGS_AS_ERRORS) if(NOT MODULE_NO_INIT) list(APPEND CPP_FILES ${module_init_src_file}) endif() if(NOT MODULE_QT_MODULE) ORGANIZE_SOURCES(SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} ) if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) set(coverage_sources ${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES} ${TOOL_CPPS}) if(MODULE_SUBPROJECTS) set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() if(NOT MODULE_HEADERS_ONLY) if(ALL_LIBRARY_DIRS) # LINK_DIRECTORIES applies only to targets which are added after the call to LINK_DIRECTORIES link_directories(${ALL_LIBRARY_DIRS}) endif(ALL_LIBRARY_DIRS) add_library(${MODULE_PROVIDES} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${DOX_FILES} ${UI_FILES}) if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_PROVIDES} ${MODULE_TARGET_DEPENDS}) endif() if(MODULE_SUBPROJECTS) set_property(TARGET ${MODULE_PROVIDES} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_PROVIDES}) endforeach() endif() if(ALL_LIBRARIES) target_link_libraries(${MODULE_PROVIDES} ${ALL_LIBRARIES}) endif(ALL_LIBRARIES) if(MINGW) target_link_libraries(${MODULE_PROVIDES} ssp) # add stack smash protection lib endif() endif() else(NOT MODULE_QT_MODULE) include(files.cmake) if(NOT MODULE_NO_INIT) list(APPEND CPP_FILES ${module_init_src_file}) endif() if(UI_FILES) QT4_WRAP_UI(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif(UI_FILES) if(MOC_H_FILES) QT4_WRAP_CPP(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES}) endif(MOC_H_FILES) if(QRC_FILES) QT4_ADD_RESOURCES(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif(QRC_FILES) set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) ORGANIZE_SOURCES(SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} UI ${UI_FILES} QRC ${QRC_FILES} MOC ${Q${KITNAME}_GENERATED_MOC_CPP} GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP} GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP}) # MITK_GENERATE_TOOLS_LIBRARY(Qmitk${LIBPOSTFIX} "NO") set(coverage_sources ${CPP_FILES} ${CORRESPONDING__H_FILES} ${GLOBBED__H_FILES} ${TXX_FILES} ${TOOL_GUI_CPPS}) set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS}) if(NOT MODULE_HEADERS_ONLY) if(ALL_LIBRARY_DIRS) # LINK_DIRECTORIES applies only to targets which are added after the call to LINK_DIRECTORIES link_directories(${ALL_LIBRARY_DIRS}) endif(ALL_LIBRARY_DIRS) add_library(${MODULE_PROVIDES} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) target_link_libraries(${MODULE_PROVIDES} ${QT_LIBRARIES} ${ALL_LIBRARIES} QVTK) if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_PROVIDES} ${MODULE_TARGET_DEPENDS}) endif() if(MINGW) target_link_libraries(${MODULE_PROVIDES} ssp) # add stack smash protection lib endif() if(MODULE_SUBPROJECTS) set_property(TARGET ${MODULE_PROVIDES} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_PROVIDES}) endforeach() endif() endif() endif(NOT MODULE_QT_MODULE) if(NOT MODULE_HEADERS_ONLY) # Apply properties to the module target. set_target_properties(${MODULE_PROVIDES} PROPERTIES COMPILE_FLAGS "${module_compile_flags}" ) endif() # install only if shared lib (for now) if(NOT _STATIC OR MINGW) if(NOT MODULE_HEADERS_ONLY) # # deprecated: MITK_INSTALL_TARGETS(${MODULE_PROVIDES}) endif() endif(NOT _STATIC OR MINGW) endif(NOT MODULE_QT_MODULE OR MITK_USE_QT) endif(MODULE_IS_ENABLED) endif(_MISSING_DEP) endif(NOT MODULE_IS_EXCLUDED) if(NOT MODULE_IS_ENABLED) _MITK_CREATE_MODULE_CONF() endif(NOT MODULE_IS_ENABLED) endmacro(MITK_CREATE_MODULE) diff --git a/CMake/mitkSetupVariables.cmake b/CMake/mitkSetupVariables.cmake index a47d6d097b..25a9a3e5aa 100644 --- a/CMake/mitkSetupVariables.cmake +++ b/CMake/mitkSetupVariables.cmake @@ -1,161 +1,161 @@ if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() set(LIBPOSTFIX "") # MITK_VERSION set(MITK_VERSION_MAJOR "2012") set(MITK_VERSION_MINOR "02") set(MITK_VERSION_PATCH "99") set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() #----------------------------------- # Configuration of module system #----------------------------------- set(MODULES_CONF_DIRNAME modulesConf) set(MODULES_CONF_DIRS ${MITK_BINARY_DIR}/${MODULES_CONF_DIRNAME}) if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() # build the MITK_INCLUDE_DIRS variable -set(MITK_INCLUDE_DIRS ${PROJECT_BINARY_DIR}) +set(MITK_INCLUDE_DIRS + ${ITK_INCLUDE_DIRS} + ${VTK_INCLUDE_DIRS} + ${PROJECT_BINARY_DIR} # contains mitkConfig.h and similar files + ${MODULES_CONF_DIRS} # contains module *Exports.h files + ) set(CORE_DIRECTORIES Common DataManagement Algorithms IO Rendering Interactions Controllers Service) foreach(d ${CORE_DIRECTORIES}) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Core/Code/${d}) endforeach() #list(APPEND MITK_INCLUDE_DIRS #${ITK_INCLUDE_DIRS} #${VTK_INCLUDE_DIRS} # ) #foreach(d Utilities Utilities/ipPic Utilities/IIL4MITK Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) foreach(d Utilities Utilities/ipPic Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${d}) endforeach() list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/Utilities/mbilog) if(WIN32) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipPic/win32) endif() # additional include dirs variables set(ANN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ann/include) set(IPSEGMENTATION_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipSegmentation) # variables containing librariy names set(MITK_CORE_LIBRARIES Mitk) set(VTK_FOR_MITK_LIBRARIES vtkGraphics vtkCommon vtkFiltering vtkftgl vtkGraphics vtkHybrid vtkImaging vtkIO vtkParallel vtkRendering vtkVolumeRendering vtkWidgets ${VTK_JPEG_LIBRARIES} ${VTK_PNG_LIBRARIES} ${VTK_ZLIB_LIBRARIES} ${VTK_EXPAT_LIBRARIES} ${VTK_FREETYPE_LIBRARIES} ) # TODO: maybe solve this with lib depends mechanism of CMake set(UTIL_FOR_MITK_LIBRARIES mitkIpPic mitkIpFunc mbilog) set(LIBRARIES_FOR_MITK_CORE ${UTIL_FOR_MITK_LIBRARIES} ${VTK_FOR_MITK_LIBRARIES} ${ITK_LIBRARIES} ) set(MITK_LIBRARIES ${MITK_CORE_LIBRARIES} ${LIBRARIES_FOR_MITK_CORE} pic2vtk #IIL4MITK ipSegmentation ann ) # variables used in CMake macros which are called from external projects set(MITK_VTK_LIBRARY_DIRS ${VTK_LIBRARY_DIRS}) set(MITK_ITK_LIBRARY_DIRS ${ITK_LIBRARY_DIRS}) # variables containing link directories set(MITK_LIBRARY_DIRS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) set(MITK_LINK_DIRECTORIES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${ITK_LIBRARY_DIRS} ${VTK_LIBRARY_DIRS} ${GDCM_LIBRARY_DIRS}) # Qt support if(MITK_USE_QT) find_package(Qt4 REQUIRED) set(QMITK_INCLUDE_DIRS ${MITK_INCLUDE_DIRS} - ${CMAKE_CURRENT_SOURCE_DIR}/CoreUI/Qmitk - ${PROJECT_BINARY_DIR}/CoreUI/Qmitk + ${CMAKE_CURRENT_SOURCE_DIR}/Modules/Qmitk + ${PROJECT_BINARY_DIR}/Modules/Qmitk ) - - foreach(d QmitkApplicationBase QmitkModels QmitkPropertyObservers) - list(APPEND QMITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/CoreUI/Qmitk/${d}) - endforeach() - list(APPEND QMITK_INCLUDE_DIRS ${QWT_INCLUDE_DIR}) - set(QMITK_LIBRARIES Qmitk ${MITK_LIBRARIES} ${QT_LIBRARIES}) - set(QMITK_LINK_DIRECTORIES ${MITK_LINK_DIRECTORIES} ${QT_LIBRARY_DIR}) + set(QMITK_LIBRARIES Qmitk ${MITK_LIBRARIES}) + set(QMITK_LINK_DIRECTORIES ${MITK_LINK_DIRECTORIES}) endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # create a list of types for template instantiations of itk image access functions function(_create_type_seq TYPES seq_var seqdim_var) set(_seq ) set(_seq_dim ) string(REPLACE "," ";" _pixeltypes "${TYPES}") foreach(_pixeltype ${_pixeltypes}) set(_seq "${_seq}(${_pixeltype})") set(_seq_dim "${_seq_dim}((${_pixeltype},dim))") endforeach() set(${seq_var} "${_seq}" PARENT_SCOPE) set(${seqdim_var} "${_seq_dim}" PARENT_SCOPE) endfunction() set(MITK_ACCESSBYITK_PIXEL_TYPES ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ ) set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ ) foreach(_type INTEGRAL FLOATING COMPOSITE) set(_typelist "${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES}") if(_typelist) if(MITK_ACCESSBYITK_PIXEL_TYPES) set(MITK_ACCESSBYITK_PIXEL_TYPES "${MITK_ACCESSBYITK_PIXEL_TYPES},${_typelist}") else() set(MITK_ACCESSBYITK_PIXEL_TYPES "${_typelist}") endif() endif() _create_type_seq("${_typelist}" MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ "${MITK_ACCESSBYITK_PIXEL_TYPES_SEQ}${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ}") set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ "${MITK_ACCESSBYITK_TYPES_DIMN_SEQ}${MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ}") endforeach() set(MITK_ACCESSBYITK_DIMENSIONS_SEQ ) string(REPLACE "," ";" _dimensions "${MITK_ACCESSBYITK_DIMENSIONS}") foreach(_dimension ${_dimensions}) set(MITK_ACCESSBYITK_DIMENSIONS_SEQ "${MITK_ACCESSBYITK_DIMENSIONS_SEQ}(${_dimension})") endforeach() diff --git a/CMakeExternals/MITKData.cmake b/CMakeExternals/MITKData.cmake index 31f5eff67b..8c60c69ea2 100644 --- a/CMakeExternals/MITKData.cmake +++ b/CMakeExternals/MITKData.cmake @@ -1,39 +1,39 @@ #----------------------------------------------------------------------------- # MITK Data #----------------------------------------------------------------------------- # Sanity checks if(DEFINED MITK_DATA_DIR AND NOT EXISTS ${MITK_DATA_DIR}) message(FATAL_ERROR "MITK_DATA_DIR variable is defined but corresponds to non-existing directory") endif() set(proj MITK-Data) set(proj_DEPENDENCIES) set(MITK-Data_DEPENDS ${proj}) if(BUILD_TESTING) - set(revision_tag 6572126b) + set(revision_tag 578a7578) #if(${proj}_REVISION_TAG) # set(revision_tag ${${proj}_REVISION_TAG}) #endif() ExternalProject_Add(${proj} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/MITK-Data_${revision_tag}.tar.gz - URL_MD5 ad2a35e2902572d6ba99a5e8e129b05e + URL_MD5 c7e6573a559d70363231c22ba7eabcb8 UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${proj_DEPENDENCIES} ) set(MITK_DATA_DIR ${ep_source_dir}/${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif(BUILD_TESTING) diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index 3f905d67b3..8e95245707 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,93 +1,94 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else(WIN32) option(VTK_USE_SYSTEM_FREETYPE ON) endif(WIN32) # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF -DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW ) endif() if(MITK_USE_Python) list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=ON -DVTK_USE_TK:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) endif() if(MITK_USE_QT) list(APPEND additional_cmake_args -DDESIRED_QT_VERSION:STRING=4 -DVTK_USE_GUISUPPORT:BOOL=ON -DVTK_USE_QVTK_QTOPENGL:BOOL=ON -DVTK_USE_QT:BOOL=ON -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() option(MITK_USE_VTK_5_8_IN_SUPERBUILD OFF) if(CMAKE_CXX_COMPILER MATCHES clang) if(NOT MITK_USE_VTK_5_8_IN_SUPERBUILD) MESSAGE(STATUS "Forcing VTK 5.8 since we're using clang") endif() SET(MITK_USE_VTK_5_8_IN_SUPERBUILD ON CACHE BOOL "Use VTK 5.8 in MITK superbuild" FORCE) endif() if(MITK_USE_VTK_5_8_IN_SUPERBUILD) set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/vtk-5.8.0.tar.gz) set(VTK_URL_MD5 37b7297d02d647cc6ca95b38174cb41f) else() set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/vtk-5.6.1.tar.gz) set(VTK_URL_MD5 b80a76435207c5d0f74dfcab15b75181) endif() ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} INSTALL_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON -DVTK_USE_PARALLEL:BOOL=ON -DVTK_USE_CHARTS:BOOL=OFF -DVTK_USE_QTCHARTS:BOOL=ON -DVTK_USE_GEOVIS:BOOL=OFF -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_USE_QVTK_QTOPENGL:BOOL=OFF + -DVTK_LEGACY_REMOVE:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp index ae8c58e11c..d3a4c46577 100644 --- a/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp +++ b/Core/Code/Algorithms/mitkClippedSurfaceBoundsCalculator.cpp @@ -1,276 +1,291 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkClippedSurfaceBoundsCalculator.h" #include "mitkLine.h" #define ROUND_P(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5)) mitk::ClippedSurfaceBoundsCalculator::ClippedSurfaceBoundsCalculator( const mitk::PlaneGeometry* geometry, mitk::Image::Pointer image): m_PlaneGeometry(NULL), m_Geometry3D(NULL), m_Image(NULL) { // initialize with meaningless slice indices m_MinMaxOutput.clear(); for(int i = 0; i < 3; i++) { m_MinMaxOutput.push_back( OutputType( std::numeric_limits::max() , std::numeric_limits::min() )); } this->SetInput(geometry, image); } mitk::ClippedSurfaceBoundsCalculator::ClippedSurfaceBoundsCalculator( const mitk::Geometry3D* geometry, mitk::Image::Pointer image): m_PlaneGeometry(NULL), m_Geometry3D(NULL), m_Image(NULL) { // initialize with meaningless slice indices m_MinMaxOutput.clear(); for(int i = 0; i < 3; i++) { m_MinMaxOutput.push_back( OutputType( std::numeric_limits::max() , std::numeric_limits::min() )); } this->SetInput(geometry, image); } mitk::ClippedSurfaceBoundsCalculator::~ClippedSurfaceBoundsCalculator() { } void mitk::ClippedSurfaceBoundsCalculator::SetInput( const mitk::PlaneGeometry* geometry, mitk::Image* image) { if(geometry && image) { this->m_PlaneGeometry = geometry; this->m_Image = image; this->m_Geometry3D = NULL; //Not possible to set both } } void mitk::ClippedSurfaceBoundsCalculator::SetInput( const mitk::Geometry3D* geometry, mitk::Image* image) { if(geometry && image) { this->m_Geometry3D = geometry; this->m_Image = image; this->m_PlaneGeometry = NULL; //Not possible to set both } } mitk::ClippedSurfaceBoundsCalculator::OutputType mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionX() { return this->m_MinMaxOutput[0]; } mitk::ClippedSurfaceBoundsCalculator::OutputType mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionY() { return this->m_MinMaxOutput[1]; } mitk::ClippedSurfaceBoundsCalculator::OutputType mitk::ClippedSurfaceBoundsCalculator::GetMinMaxSpatialDirectionZ() { return this->m_MinMaxOutput[2]; } void mitk::ClippedSurfaceBoundsCalculator::Update() { this->m_MinMaxOutput.clear(); for(int i = 0; i < 3; i++) { this->m_MinMaxOutput.push_back(OutputType( std::numeric_limits::max() , std::numeric_limits::min() )); } if(m_PlaneGeometry.IsNotNull()) { this->CalculateIntersectionPoints(m_PlaneGeometry); } else if(m_Geometry3D.IsNotNull()) { // go through all slices of the image, ... const mitk::SlicedGeometry3D* slicedGeometry3D = dynamic_cast( m_Geometry3D.GetPointer() ); int allSlices = slicedGeometry3D->GetSlices(); this->CalculateIntersectionPoints(dynamic_cast(slicedGeometry3D->GetGeometry2D(0))); this->CalculateIntersectionPoints(dynamic_cast(slicedGeometry3D->GetGeometry2D(allSlices-1))); } } void mitk::ClippedSurfaceBoundsCalculator::CalculateIntersectionPoints(const mitk::PlaneGeometry* geometry) { // SEE HEADER DOCUMENTATION for explanation typedef std::vector< std::pair > EdgesVector; Point3D origin; Vector3D xDirection, yDirection, zDirection; const Vector3D spacing = m_Image->GetGeometry()->GetSpacing(); origin = m_Image->GetGeometry()->GetOrigin(); //Left, bottom, front //Get axis vector for the spatial directions xDirection = m_Image->GetGeometry()->GetAxisVector(1); yDirection = m_Image->GetGeometry()->GetAxisVector(0); zDirection = m_Image->GetGeometry()->GetAxisVector(2); /* * For the calculation of the intersection points we need as corner points the center-based image coordinates. * With the method GetCornerPoint() of the class Geometry3D we only get the corner-based coordinates. * Therefore we need to calculate the center-based corner points here. For that we add/substract the corner- * based coordinates with the spacing of the geometry3D. */ for( int i = 0; i < 3; i++ ) { if(xDirection[i] < 0) { xDirection[i] += spacing[i]; } else if( xDirection[i] > 0 ) { xDirection[i] -= spacing[i]; } if(yDirection[i] < 0) { yDirection[i] += spacing[i]; } else if( yDirection[i] > 0 ) { yDirection[i] -= spacing[i]; } if(zDirection[i] < 0) { zDirection[i] += spacing[i]; } else if( zDirection[i] > 0 ) { zDirection[i] -= spacing[i]; } } Point3D leftBottomFront, leftTopFront, leftBottomBack, leftTopBack; Point3D rightBottomFront, rightTopFront, rightBottomBack, rightTopBack; leftBottomFront = origin; leftTopFront = origin + yDirection; leftBottomBack = origin + zDirection; leftTopBack = origin + yDirection + zDirection; rightBottomFront = origin + xDirection; rightTopFront = origin + xDirection + yDirection; rightBottomBack = origin + xDirection + zDirection; rightTopBack = origin + xDirection + yDirection + zDirection; EdgesVector edgesOf3DBox; edgesOf3DBox.push_back(std::make_pair(leftBottomBack, // x = left=xfront, y=bottom=yfront, z=front=zfront leftTopFront)); // left, top, front edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front leftBottomBack)); // left, bottom, back edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front rightBottomFront)); // right, bottom, front edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front rightTopFront)); // right, top, front edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front leftTopBack)); // left, top, back edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front rightTopBack)); // right, top, back edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front rightBottomFront)); // right, bottom, front edgesOf3DBox.push_back(std::make_pair(rightBottomFront, // right, bottom, front rightBottomBack)); // right, bottom, back edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back leftBottomBack)); // left, bottom, back edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back rightTopBack)); // right, top, back edgesOf3DBox.push_back(std::make_pair(rightTopBack, // right, top, back leftTopBack)); // left, top, back edgesOf3DBox.push_back(std::make_pair(leftTopBack, // left, top, back leftBottomBack)); // left, bottom, back for (EdgesVector::iterator iterator = edgesOf3DBox.begin(); iterator != edgesOf3DBox.end();iterator++) { Point3D startPoint = (*iterator).first; // start point of the line Point3D endPoint = (*iterator).second; // end point of the line Vector3D lineDirection = endPoint - startPoint; mitk::Line3D line(startPoint, lineDirection); Point3D intersectionWorldPoint; intersectionWorldPoint.Fill(std::numeric_limits::min()); // Get intersection point of line and plane geometry geometry->IntersectionPoint(line, intersectionWorldPoint); double t = -1.0; bool doesLineIntersectWithPlane(false); if(line.GetDirection().GetNorm() < mitk::eps && geometry->Distance(line.GetPoint1()) < mitk::sqrteps) { t = 1.0; doesLineIntersectWithPlane = true; intersectionWorldPoint = line.GetPoint1(); } else { geometry->IntersectionPoint(line, intersectionWorldPoint); doesLineIntersectWithPlane = geometry->IntersectionPointParam(line, t); } mitk::Point3D intersectionIndexPoint; //Get index point m_Image->GetGeometry()->WorldToIndex(intersectionWorldPoint, intersectionIndexPoint); if ( doesLineIntersectWithPlane && -mitk::sqrteps <= t && t <= 1.0 + mitk::sqrteps ) { for(int dim = 0; dim < 3; dim++) { // minimum //If new point value is lower than old if( this->m_MinMaxOutput[dim].first > ROUND_P(intersectionIndexPoint[dim]) ) { this->m_MinMaxOutput[dim].first = ROUND_P(intersectionIndexPoint[dim]); //set new value } // maximum //If new point value is higher than old if( this->m_MinMaxOutput[dim].second < ROUND_P(intersectionIndexPoint[dim]) ) { this->m_MinMaxOutput[dim].second = ROUND_P(intersectionIndexPoint[dim]); //set new value } } } } } diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.cpp b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp new file mode 100644 index 0000000000..bbb5600f18 --- /dev/null +++ b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp @@ -0,0 +1,592 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "mitkExtractSliceFilter.h" +#include +#include +#include +#include +#include +#include + + +mitk::ExtractSliceFilter::ExtractSliceFilter(vtkImageReslice* reslicer ){ + + if(reslicer == NULL){ + m_Reslicer = vtkSmartPointer::New(); + } + else + { + m_Reslicer = reslicer; + } + + m_TimeStep = 0; + m_Reslicer->ReleaseDataFlagOn(); + m_InterpolationMode = ExtractSliceFilter::RESLICE_NEAREST; + m_ResliceTransform = NULL; + m_InPlaneResampleExtentByGeometry = false; + m_OutPutSpacing = new mitk::ScalarType[2]; + m_OutputDimension = 2; + m_ZSpacing = 1.0; + m_ZMin = 0; + m_ZMax = 0; + m_VtkOutputRequested = false; + +} + +mitk::ExtractSliceFilter::~ExtractSliceFilter(){ + m_ResliceTransform = NULL; + m_WorldGeometry = NULL; + delete [] m_OutPutSpacing; +} + +void mitk::ExtractSliceFilter::GenerateOutputInformation(){ + //TODO try figure out how to set the specs of the slice before it is actually extracted + /*Image::Pointer output = this->GetOutput(); + Image::ConstPointer input = this->GetInput(); + if (input.IsNull()) return; + unsigned int dimensions[2]; + dimensions[0] = m_WorldGeometry->GetExtent(0); + dimensions[1] = m_WorldGeometry->GetExtent(1); + output->Initialize(input->GetPixelType(), 2, dimensions, 1);*/ +} + +void mitk::ExtractSliceFilter::GenerateInputRequestedRegion(){ + //As we want all pixel information fo the image in our plane, the requested region + //is set to the largest possible region in the image. + //This is needed because an oblique plane has a larger extent then the image + //and the in pipeline it is checked via PropagateResquestedRegion(). But the + //extent of the slice is actually fitting because it is oblique within the image. + ImageToImageFilter::InputImagePointer input = const_cast< ImageToImageFilter::InputImageType* > ( this->GetInput() ); + input->SetRequestedRegionToLargestPossibleRegion(); +} + + +mitk::ScalarType* mitk::ExtractSliceFilter::GetOutputSpacing(){ + return m_OutPutSpacing; +} + + +void mitk::ExtractSliceFilter::GenerateData(){ + + mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); + + if (!input) + { + MITK_ERROR << "mitk::ExtractSliceFilter: No input image available. Please set the input!" << std::endl; + itkExceptionMacro("mitk::ExtractSliceFilter: No input image available. Please set the input!"); + return; + } + + if(!m_WorldGeometry) + { + MITK_ERROR << "mitk::ExtractSliceFilter: No Geometry for reslicing available." << std::endl; + itkExceptionMacro("mitk::ExtractSliceFilter: No Geometry for reslicing available."); + return; + } + + + const TimeSlicedGeometry *inputTimeGeometry = this->GetInput()->GetTimeSlicedGeometry(); + if ( ( inputTimeGeometry == NULL ) + || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) + { + itkWarningMacro(<<"Error reading input image TimeSlicedGeometry."); + return; + } + + // is it a valid timeStep? + if ( inputTimeGeometry->IsValidTime( m_TimeStep ) == false ) + { + itkWarningMacro(<<"This is not a valid timestep: "<< m_TimeStep ); + return; + } + + // check if there is something to display. + if ( ! input->IsVolumeSet( m_TimeStep ) ) + { + itkWarningMacro(<<"No volume data existent at given timestep "<< m_TimeStep ); + return; + } + + + + + /*================#BEGIN setup vtkImageRslice properties================*/ + Point3D origin; + Vector3D right, bottom, normal; + double widthInMM, heightInMM; + Vector2D extent; + + + const PlaneGeometry* planeGeometry = dynamic_cast(m_WorldGeometry); + + + if ( planeGeometry != NULL ) + { + //if the worldGeomatry is a PlaneGeometry everthing is straight forward + + origin = planeGeometry->GetOrigin(); + right = planeGeometry->GetAxisVector( 0 ); + bottom = planeGeometry->GetAxisVector( 1 ); + normal = planeGeometry->GetNormal(); + + if ( m_InPlaneResampleExtentByGeometry ) + { + // Resampling grid corresponds to the current world geometry. This + // means that the spacing of the output 2D image depends on the + // currently selected world geometry, and *not* on the image itself. + extent[0] = m_WorldGeometry->GetExtent( 0 ); + extent[1] = m_WorldGeometry->GetExtent( 1 ); + } + else + { + // Resampling grid corresponds to the input geometry. This means that + // the spacing of the output 2D image is directly derived from the + // associated input image, regardless of the currently selected world + // geometry. + Vector3D rightInIndex, bottomInIndex; + inputTimeGeometry->GetGeometry3D( m_TimeStep )->WorldToIndex( right, rightInIndex ); + inputTimeGeometry->GetGeometry3D( m_TimeStep )->WorldToIndex( bottom, bottomInIndex ); + extent[0] = rightInIndex.GetNorm(); + extent[1] = bottomInIndex.GetNorm(); + } + + // Get the extent of the current world geometry and calculate resampling + // spacing therefrom. + widthInMM = m_WorldGeometry->GetExtentInMM( 0 ); + heightInMM = m_WorldGeometry->GetExtentInMM( 1 ); + + + m_OutPutSpacing[0] = widthInMM / extent[0]; + m_OutPutSpacing[1] = heightInMM / extent[1]; + + + right.Normalize(); + bottom.Normalize(); + normal.Normalize(); + + + /* + * Transform the origin to center based coordinates. + * Note: + * This is needed besause vtk's origin is center based too (!!!) ( see 'The VTK book' page 88 ) + * and the worldGeometry surrouding the image is no imageGeometry. So the worldGeometry + * has its origin at the corner of the voxel and needs to be transformed. + */ + origin += right * ( m_OutPutSpacing[0] * 0.5 ); + origin += bottom * ( m_OutPutSpacing[1] * 0.5 ); + + + + //set the tranform for reslicing. + // Use inverse transform of the input geometry for reslicing the 3D image. + // This is needed if the image volume already transformed + if(m_ResliceTransform != NULL) + m_Reslicer->SetResliceTransform(m_ResliceTransform->GetVtkTransform()->GetLinearInverse()); + + + // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D), + // else the background of the image turns out gray + m_Reslicer->SetBackgroundLevel( -32768 ); + + } + else{ + //Code for curved planes, mostly taken 1:1 from imageVtkMapper2D and not tested yet. + // Do we have an AbstractTransformGeometry? + // This is the case for AbstractTransformGeometry's (e.g. a ThinPlateSplineCurvedGeometry ) + const mitk::AbstractTransformGeometry* abstractGeometry = + dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); + + if(abstractGeometry != NULL) + { + m_ResliceTransform = abstractGeometry; + + extent[0] = abstractGeometry->GetParametricExtent(0); + extent[1] = abstractGeometry->GetParametricExtent(1); + + widthInMM = abstractGeometry->GetParametricExtentInMM(0); + heightInMM = abstractGeometry->GetParametricExtentInMM(1); + + m_OutPutSpacing[0] = widthInMM / extent[0]; + m_OutPutSpacing[1] = heightInMM / extent[1]; + + origin = abstractGeometry->GetPlane()->GetOrigin(); + + right = abstractGeometry->GetPlane()->GetAxisVector(0); + right.Normalize(); + + bottom = abstractGeometry->GetPlane()->GetAxisVector(1); + bottom.Normalize(); + + normal = abstractGeometry->GetPlane()->GetNormal(); + normal.Normalize(); + + // Use a combination of the InputGeometry *and* the possible non-rigid + // AbstractTransformGeometry for reslicing the 3D Image + vtkSmartPointer composedResliceTransform = vtkGeneralTransform::New(); + composedResliceTransform->Identity(); + composedResliceTransform->Concatenate( + inputTimeGeometry->GetGeometry3D( m_TimeStep )->GetVtkTransform()->GetLinearInverse() ); + composedResliceTransform->Concatenate( + abstractGeometry->GetVtkAbstractTransform() + ); + + m_Reslicer->SetResliceTransform( composedResliceTransform ); + composedResliceTransform->UnRegister( NULL ); // decrease RC + + // Set background level to BLACK instead of translucent, to avoid + // boundary artifacts (see Geometry2DDataVtkMapper3D) + m_Reslicer->SetBackgroundLevel( -1023 ); + } + else + { + itkExceptionMacro("mitk::ExtractSliceFilter: No fitting geometry for reslice axis!"); + return; + } + + } + + if(m_ResliceTransform != NULL){ + //if the resliceTransform is set the reslice axis are recalculated. + //Thus the geometry information is not fitting. Therefor a unitSpacingFilter + //is used to set up a global spacing of 1 and compensate the transform. + vtkSmartPointer unitSpacingImageFilter = vtkSmartPointer::New() ; + unitSpacingImageFilter->ReleaseDataFlagOn(); + + unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); + unitSpacingImageFilter->SetInput( input->GetVtkImageData(m_TimeStep) ); + + m_Reslicer->SetInput(unitSpacingImageFilter->GetOutput() ); + } + else + { + //if no tranform is set the image can be used directly + m_Reslicer->SetInput(input->GetVtkImageData(m_TimeStep)); + } + + + /*setup the plane where vktImageReslice extracts the slice*/ + + //ResliceAxesOrigin is the ancor point of the plane + double originInVtk[3]; + itk2vtk(origin, originInVtk); + m_Reslicer->SetResliceAxesOrigin(originInVtk); + + + //the cosines define the plane: x and y are the direction vectors, n is the planes normal + //this specifies a matrix 3x3 + // x1 y1 n1 + // x2 y2 n2 + // x3 y3 n3 + double cosines[9]; + + vnl2vtk(right.GetVnlVector(), cosines);//x + + vnl2vtk(bottom.GetVnlVector(), cosines + 3);//y + + vnl2vtk(normal.GetVnlVector(), cosines + 6);//n + + m_Reslicer->SetResliceAxesDirectionCosines(cosines); + + + //we only have one slice, not a volume + m_Reslicer->SetOutputDimensionality(m_OutputDimension); + + + //set the interpolation mode for slicing + switch(this->m_InterpolationMode){ + case RESLICE_NEAREST: + m_Reslicer->SetInterpolationModeToNearestNeighbor(); + break; + case RESLICE_LINEAR: + m_Reslicer->SetInterpolationModeToLinear(); + break; + case RESLICE_CUBIC: + m_Reslicer->SetInterpolationModeToCubic(); + default: + //the default interpolation used by mitk + m_Reslicer->SetInterpolationModeToNearestNeighbor(); + } + + + /*========== BEGIN setup extent of the slice ==========*/ + int xMin, xMax, yMin, yMax; + + vtkFloatingPointType sliceBounds[6]; + if(m_WorldGeometry->GetReferenceGeometry()){ + + + for ( int i = 0; i < 6; ++i ) + { + sliceBounds[i] = 0.0; + } + this->GetClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds ); + + // Calculate output extent (integer values) + xMin = static_cast< int >( sliceBounds[0] / m_OutPutSpacing[0] + 0.5 ); + xMax = static_cast< int >( sliceBounds[1] / m_OutPutSpacing[0] + 0.5 ); + yMin = static_cast< int >( sliceBounds[2] / m_OutPutSpacing[1] + 0.5 ); + yMax = static_cast< int >( sliceBounds[3] / m_OutPutSpacing[1] + 0.5 ); + + }else + { + // If no reference geometry is available, we also don't know about the + // maximum plane size; + xMin = yMin = 0; + xMax = static_cast< int >( extent[0]); + yMax = static_cast< int >( extent[1]); + } + + + m_Reslicer->SetOutputExtent(xMin, xMax-1, yMin, yMax-1, m_ZMin, m_ZMax ); + /*========== END setup extent of the slice ==========*/ + + + m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); + + m_Reslicer->SetOutputSpacing( m_OutPutSpacing[0], m_OutPutSpacing[1], m_ZSpacing ); + + + //TODO check the following lines, they are responsible wether vtk error outputs appear or not + m_Reslicer->UpdateWholeExtent(); //this produces a bad allocation error for 2D images + //m_Reslicer->GetOutput()->UpdateInformation(); + //m_Reslicer->GetOutput()->SetUpdateExtentToWholeExtent(); + + //start the pipeline + m_Reslicer->Update(); + + /*================ #END setup vtkImageRslice properties================*/ + + if(m_VtkOutputRequested){ + return; + //no converting to mitk + //no mitk geometry will be set, as the output is vtkImageData only!!! + } + else + { + /*================ #BEGIN Get the slice from vtkImageReslice and convert it to mit::Image================*/ + vtkImageData* reslicedImage; + reslicedImage = m_Reslicer->GetOutput(); + + + + if(!reslicedImage) + { + itkWarningMacro(<<"Reslicer returned empty image"); + return; + } + + + mitk::Image::Pointer resultImage = this->GetOutput(); + + //initialize resultimage with the specs of the vtkImageData object returned from vtkImageReslice + resultImage->Initialize(reslicedImage); + + //transfer the voxel data + resultImage->SetVolume(reslicedImage->GetScalarPointer()); + + + //set the geometry from current worldgeometry for the reusultimage + //this is needed that the image has the correct mitk geometry + //the originalGeometry is the Geometry of the result slice + AffineGeometryFrame3D::Pointer originalGeometryAGF = m_WorldGeometry->Clone(); + Geometry2D::Pointer originalGeometry = dynamic_cast( originalGeometryAGF.GetPointer() ); + + originalGeometry->GetIndexToWorldTransform()->SetMatrix(m_WorldGeometry->GetIndexToWorldTransform()->GetMatrix()); + + //the origin of the worldGeometry is transformed to center based coordinates to be an imageGeometry + Point3D sliceOrigin = originalGeometry->GetOrigin(); + + sliceOrigin += right * ( m_OutPutSpacing[0] * 0.5 ); + sliceOrigin += bottom * ( m_OutPutSpacing[1] * 0.5 ); + + //a worldGeometry is no imageGeometry, thus it is manually set to true + originalGeometry->ImageGeometryOn(); + + + /*At this point we have to adjust the geometry because the origin isn't correct. + The wrong origin is related to the rotation of the current world geometry plane. + This causes errors on transfering world to index coordinates. We just shift the + origin in each direction about the amount of the expanding (needed while rotating + the plane). + */ + Vector3D axis0 = originalGeometry->GetAxisVector(0); + Vector3D axis1 = originalGeometry->GetAxisVector(1); + axis0.Normalize(); + axis1.Normalize(); + + + //adapt the origin. Note that for orthogonal planes the minima are '0' and thus the origin stays the same. + sliceOrigin += (axis0 * (xMin * m_OutPutSpacing[0])) + (axis1 * (yMin * m_OutPutSpacing[1])); + + originalGeometry->SetOrigin(sliceOrigin); + + originalGeometry->Modified(); + + + resultImage->SetGeometry( originalGeometry ); + + + /*the bounds as well as the extent of the worldGeometry are not adapted correctly during crosshair rotation. + This is only a quick fix and has to be evaluated. + The new bounds are set via the max values of the calcuted slice extent. It will look like [ 0, x, 0, y, 0, 1]. + */ + mitk::BoundingBox::BoundsArrayType boundsCopy; + boundsCopy[0] = boundsCopy[2] = boundsCopy[4] = 0; + boundsCopy[5] = 1; + boundsCopy[1] = xMax - xMin; + boundsCopy[3] = yMax - yMin; + resultImage->GetGeometry()->SetBounds(boundsCopy); + + /*================ #END Get the slice from vtkImageReslice and convert it to mitk Image================*/ + } +} + + +bool mitk::ExtractSliceFilter::GetClippedPlaneBounds(vtkFloatingPointType bounds[6]){ + + if(!m_WorldGeometry || !this->GetInput()) + return false; + + return this->GetClippedPlaneBounds(m_WorldGeometry->GetReferenceGeometry(), dynamic_cast< const PlaneGeometry * >( m_WorldGeometry ), bounds); +} + + +bool mitk::ExtractSliceFilter::GetClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) +{ + bool b = this->CalculateClippedPlaneBounds(boundingGeometry, planeGeometry, bounds); + + return b; +} + + +bool mitk::ExtractSliceFilter +::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) +{ + // Clip the plane with the bounding geometry. To do so, the corner points + // of the bounding box are transformed by the inverse transformation + // matrix, and the transformed bounding box edges derived therefrom are + // clipped with the plane z=0. The resulting min/max values are taken as + // bounds for the image reslicer. + const BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); + + BoundingBox::PointType bbMin = boundingBox->GetMinimum(); + BoundingBox::PointType bbMax = boundingBox->GetMaximum(); + + vtkPoints *points = vtkPoints::New(); + if(boundingGeometry->GetImageGeometry()) + { + points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + } + else + { + points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); + points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); + } + + vtkPoints *newPoints = vtkPoints::New(); + + vtkTransform *transform = vtkTransform::New(); + transform->Identity(); + transform->Concatenate( + planeGeometry->GetVtkTransform()->GetLinearInverse() + ); + + transform->Concatenate( boundingGeometry->GetVtkTransform() ); + + transform->TransformPoints( points, newPoints ); + transform->Delete(); + + bounds[0] = bounds[2] = 10000000.0; + bounds[1] = bounds[3] = -10000000.0; + bounds[4] = bounds[5] = 0.0; + + this->LineIntersectZero( newPoints, 0, 1, bounds ); + this->LineIntersectZero( newPoints, 1, 2, bounds ); + this->LineIntersectZero( newPoints, 2, 3, bounds ); + this->LineIntersectZero( newPoints, 3, 0, bounds ); + this->LineIntersectZero( newPoints, 0, 4, bounds ); + this->LineIntersectZero( newPoints, 1, 5, bounds ); + this->LineIntersectZero( newPoints, 2, 6, bounds ); + this->LineIntersectZero( newPoints, 3, 7, bounds ); + this->LineIntersectZero( newPoints, 4, 5, bounds ); + this->LineIntersectZero( newPoints, 5, 6, bounds ); + this->LineIntersectZero( newPoints, 6, 7, bounds ); + this->LineIntersectZero( newPoints, 7, 4, bounds ); + + // clean up vtk data + points->Delete(); + newPoints->Delete(); + + if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) + || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) + { + return false; + } + else + { + // The resulting bounds must be adjusted by the plane spacing, since we + // we have so far dealt with index coordinates + const float *planeSpacing = planeGeometry->GetFloatSpacing(); + bounds[0] *= planeSpacing[0]; + bounds[1] *= planeSpacing[0]; + bounds[2] *= planeSpacing[1]; + bounds[3] *= planeSpacing[1]; + bounds[4] *= planeSpacing[2]; + bounds[5] *= planeSpacing[2]; + return true; + } +} + +bool mitk::ExtractSliceFilter +::LineIntersectZero( vtkPoints *points, int p1, int p2, + vtkFloatingPointType *bounds ) +{ + vtkFloatingPointType point1[3]; + vtkFloatingPointType point2[3]; + points->GetPoint( p1, point1 ); + points->GetPoint( p2, point2 ); + + if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) + { + double x, y; + x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); + y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); + + if ( x < bounds[0] ) { bounds[0] = x; } + if ( x > bounds[1] ) { bounds[1] = x; } + if ( y < bounds[2] ) { bounds[2] = y; } + if ( y > bounds[3] ) { bounds[3] = y; } + bounds[4] = bounds[5] = 0.0; + return true; + } + return false; +} diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.h b/Core/Code/Algorithms/mitkExtractSliceFilter.h new file mode 100644 index 0000000000..7645d8432a --- /dev/null +++ b/Core/Code/Algorithms/mitkExtractSliceFilter.h @@ -0,0 +1,185 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkExtractSliceFilter_h_Included +#define mitkExtractSliceFilter_h_Included + + +#include "MitkExports.h" +#include "mitkImageToImageFilter.h" +#include + +#include +#include +#include +#include +#include +#include + +namespace mitk +{ + /** + \brief ExtractSliceFilter extracts a 2D abitrary oriented slice from a 3D volume. + + The filter can reslice in all orthogonal planes such as sagittal, coronal and transversal, + and is also able to reslice a abitrary oriented oblique plane. + Curved planes are specified via an AbstractTransformGeometry as the input worldgeometry. + + The convinient workflow is: + 1. Set an image as input. + 2. Set the worldGeometry2D. This defines a grid where the slice is being extracted + 3. And then start the pipeline. + + There are a few more properties that can be set to modify the behavior of the slicing. + The properties are: + - interpolation mode either Nearestneighbor, Linear or Cubic. + - a transform this is a convinient way to adapt the reslice axis for the case + that the image is transformed e.g. rotated. + - time step the time step in a timesliced volume. + - resample by geometry wether the resampling grid corresponds to the specs of the + worldgeometry or is directly derived from the input image + + By default the properties are set to: + - interpolation mode Nearestneighbor. + - a transform NULL (No transform is set). + - time step 0. + - resample by geometry false (Corresponds to input image). + */ + class MITK_CORE_EXPORT ExtractSliceFilter : public ImageToImageFilter + { + public: + + mitkClassMacro(ExtractSliceFilter, ImageToImageFilter); + itkNewMacro(ExtractSliceFilter); + + mitkNewMacro1Param(Self, vtkImageReslice*); + + /** \brief Set the axis where to reslice at.*/ + void SetWorldGeometry(const Geometry2D* geometry ){ this->m_WorldGeometry = geometry; } + + /** \brief Set the time step in the 4D volume */ + void SetTimeStep( unsigned int timestep){ this->m_TimeStep = timestep; } + unsigned int GetTimeStep(){ return this->m_TimeStep; } + + /** \brief Set a transform for the reslice axes. + * This transform is needed if the image volume itself is transformed. (Effects the reslice axis) + */ + void SetResliceTransformByGeometry(const Geometry3D* transform){ this->m_ResliceTransform = transform; } + + /** \brief Resampling grid corresponds to: false->image true->worldgeometry*/ + void SetInPlaneResampleExtentByGeometry(bool inPlaneResampleExtentByGeometry){ this->m_InPlaneResampleExtentByGeometry = inPlaneResampleExtentByGeometry; } + + /** \brief Sets the output dimension of the slice*/ + void SetOutputDimensionality(unsigned int dimension){ this->m_OutputDimension = dimension; } + + /** \brief Set the spacing in z direction manually. + * Required if the outputDimension is > 2. + */ + void SetOutputSpacingZDirection(double zSpacing){ this->m_ZSpacing = zSpacing; } + + /** \brief Set the extent in pixel for direction z manualy. + Required if the output dimension is > 2. + */ + void SetOutputExtentZDirection(int zMin, int zMax) { this->m_ZMin = zMin; this->m_ZMax = zMax; } + + /** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax] + * The method uses the input of the filter to calculate the bounds. + * It is recommended to use + * GetClippedPlaneBounds(const Geometry3D*, const PlaneGeometry*, vtkFloatingPointType*) + * if you are not sure about the input. + */ + bool GetClippedPlaneBounds(double bounds[6]); + + /** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax]*/ + bool GetClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); + + /** \brief Get the spacing of the slice. returns mitk::ScalarType[2] */ + mitk::ScalarType* GetOutputSpacing(); + + /** \brief Get Output as vtkImageData. + * Note: + * SetVtkOutputRequest(true) has to be called at least once before + * GetVtkOutput(). Otherwise the output is empty for the first update step. + */ + vtkImageData* GetVtkOutput(){ m_VtkOutputRequested = true; return m_Reslicer->GetOutput(); } + + /** Set VtkOutPutRequest to suppress the convertion of the image. + * It is suggested to use this with GetVtkOutput(). + * Note: + * SetVtkOutputRequest(true) has to be called at least once before + * GetVtkOutput(). Otherwise the output is empty for the first update step. + */ + void SetVtkOutputRequest(bool isRequested){ m_VtkOutputRequested = isRequested; } + + /** \brief Get the reslices axis matrix. + * Note: the axis are recalculated when calling SetResliceTransformByGeometry. + */ + vtkMatrix4x4* GetResliceAxes(){ + return this->m_Reslicer->GetResliceAxes(); + } + + enum ResliceInterpolation { RESLICE_NEAREST, RESLICE_LINEAR, RESLICE_CUBIC }; + + void SetInterpolationMode( ExtractSliceFilter::ResliceInterpolation interpolation){ this->m_InterpolationMode = interpolation; } + + protected: + ExtractSliceFilter(vtkImageReslice* reslicer = NULL); + virtual ~ExtractSliceFilter(); + + virtual void GenerateData(); + virtual void GenerateOutputInformation(); + virtual void GenerateInputRequestedRegion(); + + + const Geometry2D* m_WorldGeometry; + vtkSmartPointer m_Reslicer; + + unsigned int m_TimeStep; + + unsigned int m_OutputDimension; + + double m_ZSpacing; + + int m_ZMin; + + int m_ZMax; + + ResliceInterpolation m_InterpolationMode; + + const Geometry3D* m_ResliceTransform; + + bool m_InPlaneResampleExtentByGeometry;//Resampling grid corresponds to: false->image true->worldgeometry + + mitk::ScalarType* m_OutPutSpacing; + + + bool m_VtkOutputRequested; + + /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ + bool LineIntersectZero( vtkPoints *points, int p1, int p2, + vtkFloatingPointType *bounds ); + + /** \brief Calculate the bounding box of the resliced image. This is necessary for + * arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) + * will have a new bounding box, which needs to be calculated. */ + bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); + }; +} + +#endif // mitkExtractSliceFilter_h_Included \ No newline at end of file diff --git a/Core/Code/Algorithms/mitkPPArithmeticDec.h b/Core/Code/Algorithms/mitkPPArithmeticDec.h index 7a8cb469c9..17f42b51c9 100644 --- a/Core/Code/Algorithms/mitkPPArithmeticDec.h +++ b/Core/Code/Algorithms/mitkPPArithmeticDec.h @@ -1,288 +1,303 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_ARITHMETIC_DEC_HPP # define MITK_PREPROCESSOR_ARITHMETIC_DEC_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_DEC */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_DEC(x) MITK_PP_DEC_I(x) # else # define MITK_PP_DEC(x) MITK_PP_DEC_OO((x)) # define MITK_PP_DEC_OO(par) MITK_PP_DEC_I ## par # endif # # define MITK_PP_DEC_I(x) MITK_PP_DEC_ ## x # # define MITK_PP_DEC_0 0 # define MITK_PP_DEC_1 0 # define MITK_PP_DEC_2 1 # define MITK_PP_DEC_3 2 # define MITK_PP_DEC_4 3 # define MITK_PP_DEC_5 4 # define MITK_PP_DEC_6 5 # define MITK_PP_DEC_7 6 # define MITK_PP_DEC_8 7 # define MITK_PP_DEC_9 8 # define MITK_PP_DEC_10 9 # define MITK_PP_DEC_11 10 # define MITK_PP_DEC_12 11 # define MITK_PP_DEC_13 12 # define MITK_PP_DEC_14 13 # define MITK_PP_DEC_15 14 # define MITK_PP_DEC_16 15 # define MITK_PP_DEC_17 16 # define MITK_PP_DEC_18 17 # define MITK_PP_DEC_19 18 # define MITK_PP_DEC_20 19 # define MITK_PP_DEC_21 20 # define MITK_PP_DEC_22 21 # define MITK_PP_DEC_23 22 # define MITK_PP_DEC_24 23 # define MITK_PP_DEC_25 24 # define MITK_PP_DEC_26 25 # define MITK_PP_DEC_27 26 # define MITK_PP_DEC_28 27 # define MITK_PP_DEC_29 28 # define MITK_PP_DEC_30 29 # define MITK_PP_DEC_31 30 # define MITK_PP_DEC_32 31 # define MITK_PP_DEC_33 32 # define MITK_PP_DEC_34 33 # define MITK_PP_DEC_35 34 # define MITK_PP_DEC_36 35 # define MITK_PP_DEC_37 36 # define MITK_PP_DEC_38 37 # define MITK_PP_DEC_39 38 # define MITK_PP_DEC_40 39 # define MITK_PP_DEC_41 40 # define MITK_PP_DEC_42 41 # define MITK_PP_DEC_43 42 # define MITK_PP_DEC_44 43 # define MITK_PP_DEC_45 44 # define MITK_PP_DEC_46 45 # define MITK_PP_DEC_47 46 # define MITK_PP_DEC_48 47 # define MITK_PP_DEC_49 48 # define MITK_PP_DEC_50 49 # define MITK_PP_DEC_51 50 # define MITK_PP_DEC_52 51 # define MITK_PP_DEC_53 52 # define MITK_PP_DEC_54 53 # define MITK_PP_DEC_55 54 # define MITK_PP_DEC_56 55 # define MITK_PP_DEC_57 56 # define MITK_PP_DEC_58 57 # define MITK_PP_DEC_59 58 # define MITK_PP_DEC_60 59 # define MITK_PP_DEC_61 60 # define MITK_PP_DEC_62 61 # define MITK_PP_DEC_63 62 # define MITK_PP_DEC_64 63 # define MITK_PP_DEC_65 64 # define MITK_PP_DEC_66 65 # define MITK_PP_DEC_67 66 # define MITK_PP_DEC_68 67 # define MITK_PP_DEC_69 68 # define MITK_PP_DEC_70 69 # define MITK_PP_DEC_71 70 # define MITK_PP_DEC_72 71 # define MITK_PP_DEC_73 72 # define MITK_PP_DEC_74 73 # define MITK_PP_DEC_75 74 # define MITK_PP_DEC_76 75 # define MITK_PP_DEC_77 76 # define MITK_PP_DEC_78 77 # define MITK_PP_DEC_79 78 # define MITK_PP_DEC_80 79 # define MITK_PP_DEC_81 80 # define MITK_PP_DEC_82 81 # define MITK_PP_DEC_83 82 # define MITK_PP_DEC_84 83 # define MITK_PP_DEC_85 84 # define MITK_PP_DEC_86 85 # define MITK_PP_DEC_87 86 # define MITK_PP_DEC_88 87 # define MITK_PP_DEC_89 88 # define MITK_PP_DEC_90 89 # define MITK_PP_DEC_91 90 # define MITK_PP_DEC_92 91 # define MITK_PP_DEC_93 92 # define MITK_PP_DEC_94 93 # define MITK_PP_DEC_95 94 # define MITK_PP_DEC_96 95 # define MITK_PP_DEC_97 96 # define MITK_PP_DEC_98 97 # define MITK_PP_DEC_99 98 # define MITK_PP_DEC_100 99 # define MITK_PP_DEC_101 100 # define MITK_PP_DEC_102 101 # define MITK_PP_DEC_103 102 # define MITK_PP_DEC_104 103 # define MITK_PP_DEC_105 104 # define MITK_PP_DEC_106 105 # define MITK_PP_DEC_107 106 # define MITK_PP_DEC_108 107 # define MITK_PP_DEC_109 108 # define MITK_PP_DEC_110 109 # define MITK_PP_DEC_111 110 # define MITK_PP_DEC_112 111 # define MITK_PP_DEC_113 112 # define MITK_PP_DEC_114 113 # define MITK_PP_DEC_115 114 # define MITK_PP_DEC_116 115 # define MITK_PP_DEC_117 116 # define MITK_PP_DEC_118 117 # define MITK_PP_DEC_119 118 # define MITK_PP_DEC_120 119 # define MITK_PP_DEC_121 120 # define MITK_PP_DEC_122 121 # define MITK_PP_DEC_123 122 # define MITK_PP_DEC_124 123 # define MITK_PP_DEC_125 124 # define MITK_PP_DEC_126 125 # define MITK_PP_DEC_127 126 # define MITK_PP_DEC_128 127 # define MITK_PP_DEC_129 128 # define MITK_PP_DEC_130 129 # define MITK_PP_DEC_131 130 # define MITK_PP_DEC_132 131 # define MITK_PP_DEC_133 132 # define MITK_PP_DEC_134 133 # define MITK_PP_DEC_135 134 # define MITK_PP_DEC_136 135 # define MITK_PP_DEC_137 136 # define MITK_PP_DEC_138 137 # define MITK_PP_DEC_139 138 # define MITK_PP_DEC_140 139 # define MITK_PP_DEC_141 140 # define MITK_PP_DEC_142 141 # define MITK_PP_DEC_143 142 # define MITK_PP_DEC_144 143 # define MITK_PP_DEC_145 144 # define MITK_PP_DEC_146 145 # define MITK_PP_DEC_147 146 # define MITK_PP_DEC_148 147 # define MITK_PP_DEC_149 148 # define MITK_PP_DEC_150 149 # define MITK_PP_DEC_151 150 # define MITK_PP_DEC_152 151 # define MITK_PP_DEC_153 152 # define MITK_PP_DEC_154 153 # define MITK_PP_DEC_155 154 # define MITK_PP_DEC_156 155 # define MITK_PP_DEC_157 156 # define MITK_PP_DEC_158 157 # define MITK_PP_DEC_159 158 # define MITK_PP_DEC_160 159 # define MITK_PP_DEC_161 160 # define MITK_PP_DEC_162 161 # define MITK_PP_DEC_163 162 # define MITK_PP_DEC_164 163 # define MITK_PP_DEC_165 164 # define MITK_PP_DEC_166 165 # define MITK_PP_DEC_167 166 # define MITK_PP_DEC_168 167 # define MITK_PP_DEC_169 168 # define MITK_PP_DEC_170 169 # define MITK_PP_DEC_171 170 # define MITK_PP_DEC_172 171 # define MITK_PP_DEC_173 172 # define MITK_PP_DEC_174 173 # define MITK_PP_DEC_175 174 # define MITK_PP_DEC_176 175 # define MITK_PP_DEC_177 176 # define MITK_PP_DEC_178 177 # define MITK_PP_DEC_179 178 # define MITK_PP_DEC_180 179 # define MITK_PP_DEC_181 180 # define MITK_PP_DEC_182 181 # define MITK_PP_DEC_183 182 # define MITK_PP_DEC_184 183 # define MITK_PP_DEC_185 184 # define MITK_PP_DEC_186 185 # define MITK_PP_DEC_187 186 # define MITK_PP_DEC_188 187 # define MITK_PP_DEC_189 188 # define MITK_PP_DEC_190 189 # define MITK_PP_DEC_191 190 # define MITK_PP_DEC_192 191 # define MITK_PP_DEC_193 192 # define MITK_PP_DEC_194 193 # define MITK_PP_DEC_195 194 # define MITK_PP_DEC_196 195 # define MITK_PP_DEC_197 196 # define MITK_PP_DEC_198 197 # define MITK_PP_DEC_199 198 # define MITK_PP_DEC_200 199 # define MITK_PP_DEC_201 200 # define MITK_PP_DEC_202 201 # define MITK_PP_DEC_203 202 # define MITK_PP_DEC_204 203 # define MITK_PP_DEC_205 204 # define MITK_PP_DEC_206 205 # define MITK_PP_DEC_207 206 # define MITK_PP_DEC_208 207 # define MITK_PP_DEC_209 208 # define MITK_PP_DEC_210 209 # define MITK_PP_DEC_211 210 # define MITK_PP_DEC_212 211 # define MITK_PP_DEC_213 212 # define MITK_PP_DEC_214 213 # define MITK_PP_DEC_215 214 # define MITK_PP_DEC_216 215 # define MITK_PP_DEC_217 216 # define MITK_PP_DEC_218 217 # define MITK_PP_DEC_219 218 # define MITK_PP_DEC_220 219 # define MITK_PP_DEC_221 220 # define MITK_PP_DEC_222 221 # define MITK_PP_DEC_223 222 # define MITK_PP_DEC_224 223 # define MITK_PP_DEC_225 224 # define MITK_PP_DEC_226 225 # define MITK_PP_DEC_227 226 # define MITK_PP_DEC_228 227 # define MITK_PP_DEC_229 228 # define MITK_PP_DEC_230 229 # define MITK_PP_DEC_231 230 # define MITK_PP_DEC_232 231 # define MITK_PP_DEC_233 232 # define MITK_PP_DEC_234 233 # define MITK_PP_DEC_235 234 # define MITK_PP_DEC_236 235 # define MITK_PP_DEC_237 236 # define MITK_PP_DEC_238 237 # define MITK_PP_DEC_239 238 # define MITK_PP_DEC_240 239 # define MITK_PP_DEC_241 240 # define MITK_PP_DEC_242 241 # define MITK_PP_DEC_243 242 # define MITK_PP_DEC_244 243 # define MITK_PP_DEC_245 244 # define MITK_PP_DEC_246 245 # define MITK_PP_DEC_247 246 # define MITK_PP_DEC_248 247 # define MITK_PP_DEC_249 248 # define MITK_PP_DEC_250 249 # define MITK_PP_DEC_251 250 # define MITK_PP_DEC_252 251 # define MITK_PP_DEC_253 252 # define MITK_PP_DEC_254 253 # define MITK_PP_DEC_255 254 # define MITK_PP_DEC_256 255 # # endif diff --git a/Core/Code/Algorithms/mitkPPCat.h b/Core/Code/Algorithms/mitkPPCat.h index 36973a7b54..5ad7ead5c6 100644 --- a/Core/Code/Algorithms/mitkPPCat.h +++ b/Core/Code/Algorithms/mitkPPCat.h @@ -1,35 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_CAT_HPP # define MITK_PREPROCESSOR_CAT_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_CAT */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_CAT(a, b) MITK_PP_CAT_I(a, b) # else # define MITK_PP_CAT(a, b) MITK_PP_CAT_OO((a, b)) # define MITK_PP_CAT_OO(par) MITK_PP_CAT_I ## par # endif # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_CAT_I(a, b) a ## b # else # define MITK_PP_CAT_I(a, b) MITK_PP_CAT_II(a ## b) # define MITK_PP_CAT_II(res) res # endif # # endif diff --git a/Core/Code/Algorithms/mitkPPConfig.h b/Core/Code/Algorithms/mitkPPConfig.h index 39168738a8..0d302600fe 100644 --- a/Core/Code/Algorithms/mitkPPConfig.h +++ b/Core/Code/Algorithms/mitkPPConfig.h @@ -1,70 +1,85 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_CONFIG_CONFIG_HPP # define MITK_PREPROCESSOR_CONFIG_CONFIG_HPP # # /* MITK_PP_CONFIG_FLAGS */ # # define MITK_PP_CONFIG_STRICT() 0x0001 # define MITK_PP_CONFIG_IDEAL() 0x0002 # # define MITK_PP_CONFIG_MSVC() 0x0004 # define MITK_PP_CONFIG_MWCC() 0x0008 # define MITK_PP_CONFIG_BCC() 0x0010 # define MITK_PP_CONFIG_EDG() 0x0020 # define MITK_PP_CONFIG_DMC() 0x0040 # # ifndef MITK_PP_CONFIG_FLAGS # if defined(__GCCXML__) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_STRICT()) # elif defined(__WAVE__) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_STRICT()) # elif defined(__MWERKS__) && __MWERKS__ >= 0x3200 # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_STRICT()) # elif defined(__EDG__) || defined(__EDG_VERSION__) # if defined(_MSC_VER) && __EDG_VERSION__ >= 308 # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_MSVC()) # else # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_EDG() | MITK_PP_CONFIG_STRICT()) # endif # elif defined(__MWERKS__) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_MWCC()) # elif defined(__DMC__) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_DMC()) # elif defined(__BORLANDC__) && __BORLANDC__ >= 0x581 # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_STRICT()) # elif defined(__BORLANDC__) || defined(__IBMC__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_BCC()) # elif defined(_MSC_VER) # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_MSVC()) # else # define MITK_PP_CONFIG_FLAGS() (MITK_PP_CONFIG_STRICT()) # endif # endif # # /* MITK_PP_CONFIG_EXTENDED_LINE_INFO */ # # ifndef MITK_PP_CONFIG_EXTENDED_LINE_INFO # define MITK_PP_CONFIG_EXTENDED_LINE_INFO 0 # endif # # /* MITK_PP_CONFIG_ERRORS */ # # ifndef MITK_PP_CONFIG_ERRORS # ifdef NDEBUG # define MITK_PP_CONFIG_ERRORS 0 # else # define MITK_PP_CONFIG_ERRORS 1 # endif # endif # # endif diff --git a/Core/Code/Algorithms/mitkPPControlExprIIf.h b/Core/Code/Algorithms/mitkPPControlExprIIf.h index d7262de6a8..08532ff12e 100644 --- a/Core/Code/Algorithms/mitkPPControlExprIIf.h +++ b/Core/Code/Algorithms/mitkPPControlExprIIf.h @@ -1,31 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_CONTROL_EXPR_IIF_HPP # define MITK_PREPROCESSOR_CONTROL_EXPR_IIF_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_EXPR_IIF */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_EXPR_IIF(bit, expr) MITK_PP_EXPR_IIF_I(bit, expr) # else # define MITK_PP_EXPR_IIF(bit, expr) MITK_PP_EXPR_IIF_OO((bit, expr)) # define MITK_PP_EXPR_IIF_OO(par) MITK_PP_EXPR_IIF_I ## par # endif # # define MITK_PP_EXPR_IIF_I(bit, expr) MITK_PP_EXPR_IIF_ ## bit(expr) # # define MITK_PP_EXPR_IIF_0(expr) # define MITK_PP_EXPR_IIF_1(expr) expr # # endif diff --git a/Core/Code/Algorithms/mitkPPControlIIf.h b/Core/Code/Algorithms/mitkPPControlIIf.h index 565b7fd9f6..29ab7f66cc 100644 --- a/Core/Code/Algorithms/mitkPPControlIIf.h +++ b/Core/Code/Algorithms/mitkPPControlIIf.h @@ -1,34 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_CONTROL_IIF_HPP # define MITK_PREPROCESSOR_CONTROL_IIF_HPP # # include "mitkPPConfig.h" # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_IIF(bit, t, f) MITK_PP_IIF_I(bit, t, f) # else # define MITK_PP_IIF(bit, t, f) MITK_PP_IIF_OO((bit, t, f)) # define MITK_PP_IIF_OO(par) MITK_PP_IIF_I ## par # endif # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_IIF_I(bit, t, f) MITK_PP_IIF_ ## bit(t, f) # else # define MITK_PP_IIF_I(bit, t, f) MITK_PP_IIF_II(MITK_PP_IIF_ ## bit(t, f)) # define MITK_PP_IIF_II(id) id # endif # # define MITK_PP_IIF_0(t, f) f # define MITK_PP_IIF_1(t, f) t # # endif diff --git a/Core/Code/Algorithms/mitkPPControlIf.h b/Core/Code/Algorithms/mitkPPControlIf.h index 9c64d12743..f6cddffd40 100644 --- a/Core/Code/Algorithms/mitkPPControlIf.h +++ b/Core/Code/Algorithms/mitkPPControlIf.h @@ -1,30 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_CONTROL_IF_HPP # define MITK_PREPROCESSOR_CONTROL_IF_HPP # # include "mitkPPConfig.h" # include "mitkPPControlIIf.h" # include "mitkPPLogicalBool.h" # # /* MITK_PP_IF */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_IF(cond, t, f) MITK_PP_IIF(MITK_PP_BOOL(cond), t, f) # else # define MITK_PP_IF(cond, t, f) MITK_PP_IF_I(cond, t, f) # define MITK_PP_IF_I(cond, t, f) MITK_PP_IIF(MITK_PP_BOOL(cond), t, f) # endif # # endif diff --git a/Core/Code/Algorithms/mitkPPDebugError.h b/Core/Code/Algorithms/mitkPPDebugError.h index 800c390658..6ae13bca76 100644 --- a/Core/Code/Algorithms/mitkPPDebugError.h +++ b/Core/Code/Algorithms/mitkPPDebugError.h @@ -1,33 +1,48 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_DEBUG_ERROR_HPP # define MITK_PREPROCESSOR_DEBUG_ERROR_HPP # # include "mitkPPCat.h" # include "mitkPPConfig.h" # # /* MITK_PP_ERROR */ # # if MITK_PP_CONFIG_ERRORS # define MITK_PP_ERROR(code) MITK_PP_CAT(MITK_PP_ERROR_, code) # endif # # define MITK_PP_ERROR_0x0000 MITK_PP_ERROR(0x0000, MITK_PP_INDEX_OUT_OF_BOUNDS) # define MITK_PP_ERROR_0x0001 MITK_PP_ERROR(0x0001, MITK_PP_WHILE_OVERFLOW) # define MITK_PP_ERROR_0x0002 MITK_PP_ERROR(0x0002, MITK_PP_FOR_OVERFLOW) # define MITK_PP_ERROR_0x0003 MITK_PP_ERROR(0x0003, MITK_PP_REPEAT_OVERFLOW) # define MITK_PP_ERROR_0x0004 MITK_PP_ERROR(0x0004, MITK_PP_LIST_FOLD_OVERFLOW) # define MITK_PP_ERROR_0x0005 MITK_PP_ERROR(0x0005, MITK_PP_SEQ_FOLD_OVERFLOW) # define MITK_PP_ERROR_0x0006 MITK_PP_ERROR(0x0006, MITK_PP_ARITHMETIC_OVERFLOW) # define MITK_PP_ERROR_0x0007 MITK_PP_ERROR(0x0007, MITK_PP_DIVISION_BY_ZERO) # # endif diff --git a/Core/Code/Algorithms/mitkPPDetailAutoRec.h b/Core/Code/Algorithms/mitkPPDetailAutoRec.h index 42289fbe44..17775a19ff 100644 --- a/Core/Code/Algorithms/mitkPPDetailAutoRec.h +++ b/Core/Code/Algorithms/mitkPPDetailAutoRec.h @@ -1,293 +1,308 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # include "mitkPPConfig.h" # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_DMC() # include "mitkPPDetailDMCAutoRec.h" # else # # ifndef MITK_PREPROCESSOR_DETAIL_AUTO_REC_HPP # define MITK_PREPROCESSOR_DETAIL_AUTO_REC_HPP # # include "mitkPPControlIIf.h" # # /* MITK_PP_AUTO_REC */ # # define MITK_PP_AUTO_REC(pred, n) MITK_PP_NODE_ENTRY_ ## n(pred) # # define MITK_PP_NODE_ENTRY_256(p) MITK_PP_NODE_128(p)(p)(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_128(p) MITK_PP_NODE_64(p)(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_64(p) MITK_PP_NODE_32(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_32(p) MITK_PP_NODE_16(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_16(p) MITK_PP_NODE_8(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_8(p) MITK_PP_NODE_4(p)(p)(p) # define MITK_PP_NODE_ENTRY_4(p) MITK_PP_NODE_2(p)(p) # define MITK_PP_NODE_ENTRY_2(p) MITK_PP_NODE_1(p) # # define MITK_PP_NODE_128(p) MITK_PP_IIF(p(128), MITK_PP_NODE_64, MITK_PP_NODE_192) # define MITK_PP_NODE_64(p) MITK_PP_IIF(p(64), MITK_PP_NODE_32, MITK_PP_NODE_96) # define MITK_PP_NODE_32(p) MITK_PP_IIF(p(32), MITK_PP_NODE_16, MITK_PP_NODE_48) # define MITK_PP_NODE_16(p) MITK_PP_IIF(p(16), MITK_PP_NODE_8, MITK_PP_NODE_24) # define MITK_PP_NODE_8(p) MITK_PP_IIF(p(8), MITK_PP_NODE_4, MITK_PP_NODE_12) # define MITK_PP_NODE_4(p) MITK_PP_IIF(p(4), MITK_PP_NODE_2, MITK_PP_NODE_6) # define MITK_PP_NODE_2(p) MITK_PP_IIF(p(2), MITK_PP_NODE_1, MITK_PP_NODE_3) # define MITK_PP_NODE_1(p) MITK_PP_IIF(p(1), 1, 2) # define MITK_PP_NODE_3(p) MITK_PP_IIF(p(3), 3, 4) # define MITK_PP_NODE_6(p) MITK_PP_IIF(p(6), MITK_PP_NODE_5, MITK_PP_NODE_7) # define MITK_PP_NODE_5(p) MITK_PP_IIF(p(5), 5, 6) # define MITK_PP_NODE_7(p) MITK_PP_IIF(p(7), 7, 8) # define MITK_PP_NODE_12(p) MITK_PP_IIF(p(12), MITK_PP_NODE_10, MITK_PP_NODE_14) # define MITK_PP_NODE_10(p) MITK_PP_IIF(p(10), MITK_PP_NODE_9, MITK_PP_NODE_11) # define MITK_PP_NODE_9(p) MITK_PP_IIF(p(9), 9, 10) # define MITK_PP_NODE_11(p) MITK_PP_IIF(p(11), 11, 12) # define MITK_PP_NODE_14(p) MITK_PP_IIF(p(14), MITK_PP_NODE_13, MITK_PP_NODE_15) # define MITK_PP_NODE_13(p) MITK_PP_IIF(p(13), 13, 14) # define MITK_PP_NODE_15(p) MITK_PP_IIF(p(15), 15, 16) # define MITK_PP_NODE_24(p) MITK_PP_IIF(p(24), MITK_PP_NODE_20, MITK_PP_NODE_28) # define MITK_PP_NODE_20(p) MITK_PP_IIF(p(20), MITK_PP_NODE_18, MITK_PP_NODE_22) # define MITK_PP_NODE_18(p) MITK_PP_IIF(p(18), MITK_PP_NODE_17, MITK_PP_NODE_19) # define MITK_PP_NODE_17(p) MITK_PP_IIF(p(17), 17, 18) # define MITK_PP_NODE_19(p) MITK_PP_IIF(p(19), 19, 20) # define MITK_PP_NODE_22(p) MITK_PP_IIF(p(22), MITK_PP_NODE_21, MITK_PP_NODE_23) # define MITK_PP_NODE_21(p) MITK_PP_IIF(p(21), 21, 22) # define MITK_PP_NODE_23(p) MITK_PP_IIF(p(23), 23, 24) # define MITK_PP_NODE_28(p) MITK_PP_IIF(p(28), MITK_PP_NODE_26, MITK_PP_NODE_30) # define MITK_PP_NODE_26(p) MITK_PP_IIF(p(26), MITK_PP_NODE_25, MITK_PP_NODE_27) # define MITK_PP_NODE_25(p) MITK_PP_IIF(p(25), 25, 26) # define MITK_PP_NODE_27(p) MITK_PP_IIF(p(27), 27, 28) # define MITK_PP_NODE_30(p) MITK_PP_IIF(p(30), MITK_PP_NODE_29, MITK_PP_NODE_31) # define MITK_PP_NODE_29(p) MITK_PP_IIF(p(29), 29, 30) # define MITK_PP_NODE_31(p) MITK_PP_IIF(p(31), 31, 32) # define MITK_PP_NODE_48(p) MITK_PP_IIF(p(48), MITK_PP_NODE_40, MITK_PP_NODE_56) # define MITK_PP_NODE_40(p) MITK_PP_IIF(p(40), MITK_PP_NODE_36, MITK_PP_NODE_44) # define MITK_PP_NODE_36(p) MITK_PP_IIF(p(36), MITK_PP_NODE_34, MITK_PP_NODE_38) # define MITK_PP_NODE_34(p) MITK_PP_IIF(p(34), MITK_PP_NODE_33, MITK_PP_NODE_35) # define MITK_PP_NODE_33(p) MITK_PP_IIF(p(33), 33, 34) # define MITK_PP_NODE_35(p) MITK_PP_IIF(p(35), 35, 36) # define MITK_PP_NODE_38(p) MITK_PP_IIF(p(38), MITK_PP_NODE_37, MITK_PP_NODE_39) # define MITK_PP_NODE_37(p) MITK_PP_IIF(p(37), 37, 38) # define MITK_PP_NODE_39(p) MITK_PP_IIF(p(39), 39, 40) # define MITK_PP_NODE_44(p) MITK_PP_IIF(p(44), MITK_PP_NODE_42, MITK_PP_NODE_46) # define MITK_PP_NODE_42(p) MITK_PP_IIF(p(42), MITK_PP_NODE_41, MITK_PP_NODE_43) # define MITK_PP_NODE_41(p) MITK_PP_IIF(p(41), 41, 42) # define MITK_PP_NODE_43(p) MITK_PP_IIF(p(43), 43, 44) # define MITK_PP_NODE_46(p) MITK_PP_IIF(p(46), MITK_PP_NODE_45, MITK_PP_NODE_47) # define MITK_PP_NODE_45(p) MITK_PP_IIF(p(45), 45, 46) # define MITK_PP_NODE_47(p) MITK_PP_IIF(p(47), 47, 48) # define MITK_PP_NODE_56(p) MITK_PP_IIF(p(56), MITK_PP_NODE_52, MITK_PP_NODE_60) # define MITK_PP_NODE_52(p) MITK_PP_IIF(p(52), MITK_PP_NODE_50, MITK_PP_NODE_54) # define MITK_PP_NODE_50(p) MITK_PP_IIF(p(50), MITK_PP_NODE_49, MITK_PP_NODE_51) # define MITK_PP_NODE_49(p) MITK_PP_IIF(p(49), 49, 50) # define MITK_PP_NODE_51(p) MITK_PP_IIF(p(51), 51, 52) # define MITK_PP_NODE_54(p) MITK_PP_IIF(p(54), MITK_PP_NODE_53, MITK_PP_NODE_55) # define MITK_PP_NODE_53(p) MITK_PP_IIF(p(53), 53, 54) # define MITK_PP_NODE_55(p) MITK_PP_IIF(p(55), 55, 56) # define MITK_PP_NODE_60(p) MITK_PP_IIF(p(60), MITK_PP_NODE_58, MITK_PP_NODE_62) # define MITK_PP_NODE_58(p) MITK_PP_IIF(p(58), MITK_PP_NODE_57, MITK_PP_NODE_59) # define MITK_PP_NODE_57(p) MITK_PP_IIF(p(57), 57, 58) # define MITK_PP_NODE_59(p) MITK_PP_IIF(p(59), 59, 60) # define MITK_PP_NODE_62(p) MITK_PP_IIF(p(62), MITK_PP_NODE_61, MITK_PP_NODE_63) # define MITK_PP_NODE_61(p) MITK_PP_IIF(p(61), 61, 62) # define MITK_PP_NODE_63(p) MITK_PP_IIF(p(63), 63, 64) # define MITK_PP_NODE_96(p) MITK_PP_IIF(p(96), MITK_PP_NODE_80, MITK_PP_NODE_112) # define MITK_PP_NODE_80(p) MITK_PP_IIF(p(80), MITK_PP_NODE_72, MITK_PP_NODE_88) # define MITK_PP_NODE_72(p) MITK_PP_IIF(p(72), MITK_PP_NODE_68, MITK_PP_NODE_76) # define MITK_PP_NODE_68(p) MITK_PP_IIF(p(68), MITK_PP_NODE_66, MITK_PP_NODE_70) # define MITK_PP_NODE_66(p) MITK_PP_IIF(p(66), MITK_PP_NODE_65, MITK_PP_NODE_67) # define MITK_PP_NODE_65(p) MITK_PP_IIF(p(65), 65, 66) # define MITK_PP_NODE_67(p) MITK_PP_IIF(p(67), 67, 68) # define MITK_PP_NODE_70(p) MITK_PP_IIF(p(70), MITK_PP_NODE_69, MITK_PP_NODE_71) # define MITK_PP_NODE_69(p) MITK_PP_IIF(p(69), 69, 70) # define MITK_PP_NODE_71(p) MITK_PP_IIF(p(71), 71, 72) # define MITK_PP_NODE_76(p) MITK_PP_IIF(p(76), MITK_PP_NODE_74, MITK_PP_NODE_78) # define MITK_PP_NODE_74(p) MITK_PP_IIF(p(74), MITK_PP_NODE_73, MITK_PP_NODE_75) # define MITK_PP_NODE_73(p) MITK_PP_IIF(p(73), 73, 74) # define MITK_PP_NODE_75(p) MITK_PP_IIF(p(75), 75, 76) # define MITK_PP_NODE_78(p) MITK_PP_IIF(p(78), MITK_PP_NODE_77, MITK_PP_NODE_79) # define MITK_PP_NODE_77(p) MITK_PP_IIF(p(77), 77, 78) # define MITK_PP_NODE_79(p) MITK_PP_IIF(p(79), 79, 80) # define MITK_PP_NODE_88(p) MITK_PP_IIF(p(88), MITK_PP_NODE_84, MITK_PP_NODE_92) # define MITK_PP_NODE_84(p) MITK_PP_IIF(p(84), MITK_PP_NODE_82, MITK_PP_NODE_86) # define MITK_PP_NODE_82(p) MITK_PP_IIF(p(82), MITK_PP_NODE_81, MITK_PP_NODE_83) # define MITK_PP_NODE_81(p) MITK_PP_IIF(p(81), 81, 82) # define MITK_PP_NODE_83(p) MITK_PP_IIF(p(83), 83, 84) # define MITK_PP_NODE_86(p) MITK_PP_IIF(p(86), MITK_PP_NODE_85, MITK_PP_NODE_87) # define MITK_PP_NODE_85(p) MITK_PP_IIF(p(85), 85, 86) # define MITK_PP_NODE_87(p) MITK_PP_IIF(p(87), 87, 88) # define MITK_PP_NODE_92(p) MITK_PP_IIF(p(92), MITK_PP_NODE_90, MITK_PP_NODE_94) # define MITK_PP_NODE_90(p) MITK_PP_IIF(p(90), MITK_PP_NODE_89, MITK_PP_NODE_91) # define MITK_PP_NODE_89(p) MITK_PP_IIF(p(89), 89, 90) # define MITK_PP_NODE_91(p) MITK_PP_IIF(p(91), 91, 92) # define MITK_PP_NODE_94(p) MITK_PP_IIF(p(94), MITK_PP_NODE_93, MITK_PP_NODE_95) # define MITK_PP_NODE_93(p) MITK_PP_IIF(p(93), 93, 94) # define MITK_PP_NODE_95(p) MITK_PP_IIF(p(95), 95, 96) # define MITK_PP_NODE_112(p) MITK_PP_IIF(p(112), MITK_PP_NODE_104, MITK_PP_NODE_120) # define MITK_PP_NODE_104(p) MITK_PP_IIF(p(104), MITK_PP_NODE_100, MITK_PP_NODE_108) # define MITK_PP_NODE_100(p) MITK_PP_IIF(p(100), MITK_PP_NODE_98, MITK_PP_NODE_102) # define MITK_PP_NODE_98(p) MITK_PP_IIF(p(98), MITK_PP_NODE_97, MITK_PP_NODE_99) # define MITK_PP_NODE_97(p) MITK_PP_IIF(p(97), 97, 98) # define MITK_PP_NODE_99(p) MITK_PP_IIF(p(99), 99, 100) # define MITK_PP_NODE_102(p) MITK_PP_IIF(p(102), MITK_PP_NODE_101, MITK_PP_NODE_103) # define MITK_PP_NODE_101(p) MITK_PP_IIF(p(101), 101, 102) # define MITK_PP_NODE_103(p) MITK_PP_IIF(p(103), 103, 104) # define MITK_PP_NODE_108(p) MITK_PP_IIF(p(108), MITK_PP_NODE_106, MITK_PP_NODE_110) # define MITK_PP_NODE_106(p) MITK_PP_IIF(p(106), MITK_PP_NODE_105, MITK_PP_NODE_107) # define MITK_PP_NODE_105(p) MITK_PP_IIF(p(105), 105, 106) # define MITK_PP_NODE_107(p) MITK_PP_IIF(p(107), 107, 108) # define MITK_PP_NODE_110(p) MITK_PP_IIF(p(110), MITK_PP_NODE_109, MITK_PP_NODE_111) # define MITK_PP_NODE_109(p) MITK_PP_IIF(p(109), 109, 110) # define MITK_PP_NODE_111(p) MITK_PP_IIF(p(111), 111, 112) # define MITK_PP_NODE_120(p) MITK_PP_IIF(p(120), MITK_PP_NODE_116, MITK_PP_NODE_124) # define MITK_PP_NODE_116(p) MITK_PP_IIF(p(116), MITK_PP_NODE_114, MITK_PP_NODE_118) # define MITK_PP_NODE_114(p) MITK_PP_IIF(p(114), MITK_PP_NODE_113, MITK_PP_NODE_115) # define MITK_PP_NODE_113(p) MITK_PP_IIF(p(113), 113, 114) # define MITK_PP_NODE_115(p) MITK_PP_IIF(p(115), 115, 116) # define MITK_PP_NODE_118(p) MITK_PP_IIF(p(118), MITK_PP_NODE_117, MITK_PP_NODE_119) # define MITK_PP_NODE_117(p) MITK_PP_IIF(p(117), 117, 118) # define MITK_PP_NODE_119(p) MITK_PP_IIF(p(119), 119, 120) # define MITK_PP_NODE_124(p) MITK_PP_IIF(p(124), MITK_PP_NODE_122, MITK_PP_NODE_126) # define MITK_PP_NODE_122(p) MITK_PP_IIF(p(122), MITK_PP_NODE_121, MITK_PP_NODE_123) # define MITK_PP_NODE_121(p) MITK_PP_IIF(p(121), 121, 122) # define MITK_PP_NODE_123(p) MITK_PP_IIF(p(123), 123, 124) # define MITK_PP_NODE_126(p) MITK_PP_IIF(p(126), MITK_PP_NODE_125, MITK_PP_NODE_127) # define MITK_PP_NODE_125(p) MITK_PP_IIF(p(125), 125, 126) # define MITK_PP_NODE_127(p) MITK_PP_IIF(p(127), 127, 128) # define MITK_PP_NODE_192(p) MITK_PP_IIF(p(192), MITK_PP_NODE_160, MITK_PP_NODE_224) # define MITK_PP_NODE_160(p) MITK_PP_IIF(p(160), MITK_PP_NODE_144, MITK_PP_NODE_176) # define MITK_PP_NODE_144(p) MITK_PP_IIF(p(144), MITK_PP_NODE_136, MITK_PP_NODE_152) # define MITK_PP_NODE_136(p) MITK_PP_IIF(p(136), MITK_PP_NODE_132, MITK_PP_NODE_140) # define MITK_PP_NODE_132(p) MITK_PP_IIF(p(132), MITK_PP_NODE_130, MITK_PP_NODE_134) # define MITK_PP_NODE_130(p) MITK_PP_IIF(p(130), MITK_PP_NODE_129, MITK_PP_NODE_131) # define MITK_PP_NODE_129(p) MITK_PP_IIF(p(129), 129, 130) # define MITK_PP_NODE_131(p) MITK_PP_IIF(p(131), 131, 132) # define MITK_PP_NODE_134(p) MITK_PP_IIF(p(134), MITK_PP_NODE_133, MITK_PP_NODE_135) # define MITK_PP_NODE_133(p) MITK_PP_IIF(p(133), 133, 134) # define MITK_PP_NODE_135(p) MITK_PP_IIF(p(135), 135, 136) # define MITK_PP_NODE_140(p) MITK_PP_IIF(p(140), MITK_PP_NODE_138, MITK_PP_NODE_142) # define MITK_PP_NODE_138(p) MITK_PP_IIF(p(138), MITK_PP_NODE_137, MITK_PP_NODE_139) # define MITK_PP_NODE_137(p) MITK_PP_IIF(p(137), 137, 138) # define MITK_PP_NODE_139(p) MITK_PP_IIF(p(139), 139, 140) # define MITK_PP_NODE_142(p) MITK_PP_IIF(p(142), MITK_PP_NODE_141, MITK_PP_NODE_143) # define MITK_PP_NODE_141(p) MITK_PP_IIF(p(141), 141, 142) # define MITK_PP_NODE_143(p) MITK_PP_IIF(p(143), 143, 144) # define MITK_PP_NODE_152(p) MITK_PP_IIF(p(152), MITK_PP_NODE_148, MITK_PP_NODE_156) # define MITK_PP_NODE_148(p) MITK_PP_IIF(p(148), MITK_PP_NODE_146, MITK_PP_NODE_150) # define MITK_PP_NODE_146(p) MITK_PP_IIF(p(146), MITK_PP_NODE_145, MITK_PP_NODE_147) # define MITK_PP_NODE_145(p) MITK_PP_IIF(p(145), 145, 146) # define MITK_PP_NODE_147(p) MITK_PP_IIF(p(147), 147, 148) # define MITK_PP_NODE_150(p) MITK_PP_IIF(p(150), MITK_PP_NODE_149, MITK_PP_NODE_151) # define MITK_PP_NODE_149(p) MITK_PP_IIF(p(149), 149, 150) # define MITK_PP_NODE_151(p) MITK_PP_IIF(p(151), 151, 152) # define MITK_PP_NODE_156(p) MITK_PP_IIF(p(156), MITK_PP_NODE_154, MITK_PP_NODE_158) # define MITK_PP_NODE_154(p) MITK_PP_IIF(p(154), MITK_PP_NODE_153, MITK_PP_NODE_155) # define MITK_PP_NODE_153(p) MITK_PP_IIF(p(153), 153, 154) # define MITK_PP_NODE_155(p) MITK_PP_IIF(p(155), 155, 156) # define MITK_PP_NODE_158(p) MITK_PP_IIF(p(158), MITK_PP_NODE_157, MITK_PP_NODE_159) # define MITK_PP_NODE_157(p) MITK_PP_IIF(p(157), 157, 158) # define MITK_PP_NODE_159(p) MITK_PP_IIF(p(159), 159, 160) # define MITK_PP_NODE_176(p) MITK_PP_IIF(p(176), MITK_PP_NODE_168, MITK_PP_NODE_184) # define MITK_PP_NODE_168(p) MITK_PP_IIF(p(168), MITK_PP_NODE_164, MITK_PP_NODE_172) # define MITK_PP_NODE_164(p) MITK_PP_IIF(p(164), MITK_PP_NODE_162, MITK_PP_NODE_166) # define MITK_PP_NODE_162(p) MITK_PP_IIF(p(162), MITK_PP_NODE_161, MITK_PP_NODE_163) # define MITK_PP_NODE_161(p) MITK_PP_IIF(p(161), 161, 162) # define MITK_PP_NODE_163(p) MITK_PP_IIF(p(163), 163, 164) # define MITK_PP_NODE_166(p) MITK_PP_IIF(p(166), MITK_PP_NODE_165, MITK_PP_NODE_167) # define MITK_PP_NODE_165(p) MITK_PP_IIF(p(165), 165, 166) # define MITK_PP_NODE_167(p) MITK_PP_IIF(p(167), 167, 168) # define MITK_PP_NODE_172(p) MITK_PP_IIF(p(172), MITK_PP_NODE_170, MITK_PP_NODE_174) # define MITK_PP_NODE_170(p) MITK_PP_IIF(p(170), MITK_PP_NODE_169, MITK_PP_NODE_171) # define MITK_PP_NODE_169(p) MITK_PP_IIF(p(169), 169, 170) # define MITK_PP_NODE_171(p) MITK_PP_IIF(p(171), 171, 172) # define MITK_PP_NODE_174(p) MITK_PP_IIF(p(174), MITK_PP_NODE_173, MITK_PP_NODE_175) # define MITK_PP_NODE_173(p) MITK_PP_IIF(p(173), 173, 174) # define MITK_PP_NODE_175(p) MITK_PP_IIF(p(175), 175, 176) # define MITK_PP_NODE_184(p) MITK_PP_IIF(p(184), MITK_PP_NODE_180, MITK_PP_NODE_188) # define MITK_PP_NODE_180(p) MITK_PP_IIF(p(180), MITK_PP_NODE_178, MITK_PP_NODE_182) # define MITK_PP_NODE_178(p) MITK_PP_IIF(p(178), MITK_PP_NODE_177, MITK_PP_NODE_179) # define MITK_PP_NODE_177(p) MITK_PP_IIF(p(177), 177, 178) # define MITK_PP_NODE_179(p) MITK_PP_IIF(p(179), 179, 180) # define MITK_PP_NODE_182(p) MITK_PP_IIF(p(182), MITK_PP_NODE_181, MITK_PP_NODE_183) # define MITK_PP_NODE_181(p) MITK_PP_IIF(p(181), 181, 182) # define MITK_PP_NODE_183(p) MITK_PP_IIF(p(183), 183, 184) # define MITK_PP_NODE_188(p) MITK_PP_IIF(p(188), MITK_PP_NODE_186, MITK_PP_NODE_190) # define MITK_PP_NODE_186(p) MITK_PP_IIF(p(186), MITK_PP_NODE_185, MITK_PP_NODE_187) # define MITK_PP_NODE_185(p) MITK_PP_IIF(p(185), 185, 186) # define MITK_PP_NODE_187(p) MITK_PP_IIF(p(187), 187, 188) # define MITK_PP_NODE_190(p) MITK_PP_IIF(p(190), MITK_PP_NODE_189, MITK_PP_NODE_191) # define MITK_PP_NODE_189(p) MITK_PP_IIF(p(189), 189, 190) # define MITK_PP_NODE_191(p) MITK_PP_IIF(p(191), 191, 192) # define MITK_PP_NODE_224(p) MITK_PP_IIF(p(224), MITK_PP_NODE_208, MITK_PP_NODE_240) # define MITK_PP_NODE_208(p) MITK_PP_IIF(p(208), MITK_PP_NODE_200, MITK_PP_NODE_216) # define MITK_PP_NODE_200(p) MITK_PP_IIF(p(200), MITK_PP_NODE_196, MITK_PP_NODE_204) # define MITK_PP_NODE_196(p) MITK_PP_IIF(p(196), MITK_PP_NODE_194, MITK_PP_NODE_198) # define MITK_PP_NODE_194(p) MITK_PP_IIF(p(194), MITK_PP_NODE_193, MITK_PP_NODE_195) # define MITK_PP_NODE_193(p) MITK_PP_IIF(p(193), 193, 194) # define MITK_PP_NODE_195(p) MITK_PP_IIF(p(195), 195, 196) # define MITK_PP_NODE_198(p) MITK_PP_IIF(p(198), MITK_PP_NODE_197, MITK_PP_NODE_199) # define MITK_PP_NODE_197(p) MITK_PP_IIF(p(197), 197, 198) # define MITK_PP_NODE_199(p) MITK_PP_IIF(p(199), 199, 200) # define MITK_PP_NODE_204(p) MITK_PP_IIF(p(204), MITK_PP_NODE_202, MITK_PP_NODE_206) # define MITK_PP_NODE_202(p) MITK_PP_IIF(p(202), MITK_PP_NODE_201, MITK_PP_NODE_203) # define MITK_PP_NODE_201(p) MITK_PP_IIF(p(201), 201, 202) # define MITK_PP_NODE_203(p) MITK_PP_IIF(p(203), 203, 204) # define MITK_PP_NODE_206(p) MITK_PP_IIF(p(206), MITK_PP_NODE_205, MITK_PP_NODE_207) # define MITK_PP_NODE_205(p) MITK_PP_IIF(p(205), 205, 206) # define MITK_PP_NODE_207(p) MITK_PP_IIF(p(207), 207, 208) # define MITK_PP_NODE_216(p) MITK_PP_IIF(p(216), MITK_PP_NODE_212, MITK_PP_NODE_220) # define MITK_PP_NODE_212(p) MITK_PP_IIF(p(212), MITK_PP_NODE_210, MITK_PP_NODE_214) # define MITK_PP_NODE_210(p) MITK_PP_IIF(p(210), MITK_PP_NODE_209, MITK_PP_NODE_211) # define MITK_PP_NODE_209(p) MITK_PP_IIF(p(209), 209, 210) # define MITK_PP_NODE_211(p) MITK_PP_IIF(p(211), 211, 212) # define MITK_PP_NODE_214(p) MITK_PP_IIF(p(214), MITK_PP_NODE_213, MITK_PP_NODE_215) # define MITK_PP_NODE_213(p) MITK_PP_IIF(p(213), 213, 214) # define MITK_PP_NODE_215(p) MITK_PP_IIF(p(215), 215, 216) # define MITK_PP_NODE_220(p) MITK_PP_IIF(p(220), MITK_PP_NODE_218, MITK_PP_NODE_222) # define MITK_PP_NODE_218(p) MITK_PP_IIF(p(218), MITK_PP_NODE_217, MITK_PP_NODE_219) # define MITK_PP_NODE_217(p) MITK_PP_IIF(p(217), 217, 218) # define MITK_PP_NODE_219(p) MITK_PP_IIF(p(219), 219, 220) # define MITK_PP_NODE_222(p) MITK_PP_IIF(p(222), MITK_PP_NODE_221, MITK_PP_NODE_223) # define MITK_PP_NODE_221(p) MITK_PP_IIF(p(221), 221, 222) # define MITK_PP_NODE_223(p) MITK_PP_IIF(p(223), 223, 224) # define MITK_PP_NODE_240(p) MITK_PP_IIF(p(240), MITK_PP_NODE_232, MITK_PP_NODE_248) # define MITK_PP_NODE_232(p) MITK_PP_IIF(p(232), MITK_PP_NODE_228, MITK_PP_NODE_236) # define MITK_PP_NODE_228(p) MITK_PP_IIF(p(228), MITK_PP_NODE_226, MITK_PP_NODE_230) # define MITK_PP_NODE_226(p) MITK_PP_IIF(p(226), MITK_PP_NODE_225, MITK_PP_NODE_227) # define MITK_PP_NODE_225(p) MITK_PP_IIF(p(225), 225, 226) # define MITK_PP_NODE_227(p) MITK_PP_IIF(p(227), 227, 228) # define MITK_PP_NODE_230(p) MITK_PP_IIF(p(230), MITK_PP_NODE_229, MITK_PP_NODE_231) # define MITK_PP_NODE_229(p) MITK_PP_IIF(p(229), 229, 230) # define MITK_PP_NODE_231(p) MITK_PP_IIF(p(231), 231, 232) # define MITK_PP_NODE_236(p) MITK_PP_IIF(p(236), MITK_PP_NODE_234, MITK_PP_NODE_238) # define MITK_PP_NODE_234(p) MITK_PP_IIF(p(234), MITK_PP_NODE_233, MITK_PP_NODE_235) # define MITK_PP_NODE_233(p) MITK_PP_IIF(p(233), 233, 234) # define MITK_PP_NODE_235(p) MITK_PP_IIF(p(235), 235, 236) # define MITK_PP_NODE_238(p) MITK_PP_IIF(p(238), MITK_PP_NODE_237, MITK_PP_NODE_239) # define MITK_PP_NODE_237(p) MITK_PP_IIF(p(237), 237, 238) # define MITK_PP_NODE_239(p) MITK_PP_IIF(p(239), 239, 240) # define MITK_PP_NODE_248(p) MITK_PP_IIF(p(248), MITK_PP_NODE_244, MITK_PP_NODE_252) # define MITK_PP_NODE_244(p) MITK_PP_IIF(p(244), MITK_PP_NODE_242, MITK_PP_NODE_246) # define MITK_PP_NODE_242(p) MITK_PP_IIF(p(242), MITK_PP_NODE_241, MITK_PP_NODE_243) # define MITK_PP_NODE_241(p) MITK_PP_IIF(p(241), 241, 242) # define MITK_PP_NODE_243(p) MITK_PP_IIF(p(243), 243, 244) # define MITK_PP_NODE_246(p) MITK_PP_IIF(p(246), MITK_PP_NODE_245, MITK_PP_NODE_247) # define MITK_PP_NODE_245(p) MITK_PP_IIF(p(245), 245, 246) # define MITK_PP_NODE_247(p) MITK_PP_IIF(p(247), 247, 248) # define MITK_PP_NODE_252(p) MITK_PP_IIF(p(252), MITK_PP_NODE_250, MITK_PP_NODE_254) # define MITK_PP_NODE_250(p) MITK_PP_IIF(p(250), MITK_PP_NODE_249, MITK_PP_NODE_251) # define MITK_PP_NODE_249(p) MITK_PP_IIF(p(249), 249, 250) # define MITK_PP_NODE_251(p) MITK_PP_IIF(p(251), 251, 252) # define MITK_PP_NODE_254(p) MITK_PP_IIF(p(254), MITK_PP_NODE_253, MITK_PP_NODE_255) # define MITK_PP_NODE_253(p) MITK_PP_IIF(p(253), 253, 254) # define MITK_PP_NODE_255(p) MITK_PP_IIF(p(255), 255, 256) # # endif # endif diff --git a/Core/Code/Algorithms/mitkPPDetailDMCAutoRec.h b/Core/Code/Algorithms/mitkPPDetailDMCAutoRec.h index c1ca946f47..69dfd48374 100644 --- a/Core/Code/Algorithms/mitkPPDetailDMCAutoRec.h +++ b/Core/Code/Algorithms/mitkPPDetailDMCAutoRec.h @@ -1,286 +1,301 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_DETAIL_AUTO_REC_HPP # define MITK_PREPROCESSOR_DETAIL_AUTO_REC_HPP # # include "mitkPPControlIIf.h" # # /* MITK_PP_AUTO_REC */ # # define MITK_PP_AUTO_REC(pred, n) MITK_PP_NODE_ENTRY_ ## n(pred) # # define MITK_PP_NODE_ENTRY_256(p) MITK_PP_NODE_128(p)(p)(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_128(p) MITK_PP_NODE_64(p)(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_64(p) MITK_PP_NODE_32(p)(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_32(p) MITK_PP_NODE_16(p)(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_16(p) MITK_PP_NODE_8(p)(p)(p)(p) # define MITK_PP_NODE_ENTRY_8(p) MITK_PP_NODE_4(p)(p)(p) # define MITK_PP_NODE_ENTRY_4(p) MITK_PP_NODE_2(p)(p) # define MITK_PP_NODE_ENTRY_2(p) MITK_PP_NODE_1(p) # # define MITK_PP_NODE_128(p) MITK_PP_IIF(p##(128), MITK_PP_NODE_64, MITK_PP_NODE_192) # define MITK_PP_NODE_64(p) MITK_PP_IIF(p##(64), MITK_PP_NODE_32, MITK_PP_NODE_96) # define MITK_PP_NODE_32(p) MITK_PP_IIF(p##(32), MITK_PP_NODE_16, MITK_PP_NODE_48) # define MITK_PP_NODE_16(p) MITK_PP_IIF(p##(16), MITK_PP_NODE_8, MITK_PP_NODE_24) # define MITK_PP_NODE_8(p) MITK_PP_IIF(p##(8), MITK_PP_NODE_4, MITK_PP_NODE_12) # define MITK_PP_NODE_4(p) MITK_PP_IIF(p##(4), MITK_PP_NODE_2, MITK_PP_NODE_6) # define MITK_PP_NODE_2(p) MITK_PP_IIF(p##(2), MITK_PP_NODE_1, MITK_PP_NODE_3) # define MITK_PP_NODE_1(p) MITK_PP_IIF(p##(1), 1, 2) # define MITK_PP_NODE_3(p) MITK_PP_IIF(p##(3), 3, 4) # define MITK_PP_NODE_6(p) MITK_PP_IIF(p##(6), MITK_PP_NODE_5, MITK_PP_NODE_7) # define MITK_PP_NODE_5(p) MITK_PP_IIF(p##(5), 5, 6) # define MITK_PP_NODE_7(p) MITK_PP_IIF(p##(7), 7, 8) # define MITK_PP_NODE_12(p) MITK_PP_IIF(p##(12), MITK_PP_NODE_10, MITK_PP_NODE_14) # define MITK_PP_NODE_10(p) MITK_PP_IIF(p##(10), MITK_PP_NODE_9, MITK_PP_NODE_11) # define MITK_PP_NODE_9(p) MITK_PP_IIF(p##(9), 9, 10) # define MITK_PP_NODE_11(p) MITK_PP_IIF(p##(11), 11, 12) # define MITK_PP_NODE_14(p) MITK_PP_IIF(p##(14), MITK_PP_NODE_13, MITK_PP_NODE_15) # define MITK_PP_NODE_13(p) MITK_PP_IIF(p##(13), 13, 14) # define MITK_PP_NODE_15(p) MITK_PP_IIF(p##(15), 15, 16) # define MITK_PP_NODE_24(p) MITK_PP_IIF(p##(24), MITK_PP_NODE_20, MITK_PP_NODE_28) # define MITK_PP_NODE_20(p) MITK_PP_IIF(p##(20), MITK_PP_NODE_18, MITK_PP_NODE_22) # define MITK_PP_NODE_18(p) MITK_PP_IIF(p##(18), MITK_PP_NODE_17, MITK_PP_NODE_19) # define MITK_PP_NODE_17(p) MITK_PP_IIF(p##(17), 17, 18) # define MITK_PP_NODE_19(p) MITK_PP_IIF(p##(19), 19, 20) # define MITK_PP_NODE_22(p) MITK_PP_IIF(p##(22), MITK_PP_NODE_21, MITK_PP_NODE_23) # define MITK_PP_NODE_21(p) MITK_PP_IIF(p##(21), 21, 22) # define MITK_PP_NODE_23(p) MITK_PP_IIF(p##(23), 23, 24) # define MITK_PP_NODE_28(p) MITK_PP_IIF(p##(28), MITK_PP_NODE_26, MITK_PP_NODE_30) # define MITK_PP_NODE_26(p) MITK_PP_IIF(p##(26), MITK_PP_NODE_25, MITK_PP_NODE_27) # define MITK_PP_NODE_25(p) MITK_PP_IIF(p##(25), 25, 26) # define MITK_PP_NODE_27(p) MITK_PP_IIF(p##(27), 27, 28) # define MITK_PP_NODE_30(p) MITK_PP_IIF(p##(30), MITK_PP_NODE_29, MITK_PP_NODE_31) # define MITK_PP_NODE_29(p) MITK_PP_IIF(p##(29), 29, 30) # define MITK_PP_NODE_31(p) MITK_PP_IIF(p##(31), 31, 32) # define MITK_PP_NODE_48(p) MITK_PP_IIF(p##(48), MITK_PP_NODE_40, MITK_PP_NODE_56) # define MITK_PP_NODE_40(p) MITK_PP_IIF(p##(40), MITK_PP_NODE_36, MITK_PP_NODE_44) # define MITK_PP_NODE_36(p) MITK_PP_IIF(p##(36), MITK_PP_NODE_34, MITK_PP_NODE_38) # define MITK_PP_NODE_34(p) MITK_PP_IIF(p##(34), MITK_PP_NODE_33, MITK_PP_NODE_35) # define MITK_PP_NODE_33(p) MITK_PP_IIF(p##(33), 33, 34) # define MITK_PP_NODE_35(p) MITK_PP_IIF(p##(35), 35, 36) # define MITK_PP_NODE_38(p) MITK_PP_IIF(p##(38), MITK_PP_NODE_37, MITK_PP_NODE_39) # define MITK_PP_NODE_37(p) MITK_PP_IIF(p##(37), 37, 38) # define MITK_PP_NODE_39(p) MITK_PP_IIF(p##(39), 39, 40) # define MITK_PP_NODE_44(p) MITK_PP_IIF(p##(44), MITK_PP_NODE_42, MITK_PP_NODE_46) # define MITK_PP_NODE_42(p) MITK_PP_IIF(p##(42), MITK_PP_NODE_41, MITK_PP_NODE_43) # define MITK_PP_NODE_41(p) MITK_PP_IIF(p##(41), 41, 42) # define MITK_PP_NODE_43(p) MITK_PP_IIF(p##(43), 43, 44) # define MITK_PP_NODE_46(p) MITK_PP_IIF(p##(46), MITK_PP_NODE_45, MITK_PP_NODE_47) # define MITK_PP_NODE_45(p) MITK_PP_IIF(p##(45), 45, 46) # define MITK_PP_NODE_47(p) MITK_PP_IIF(p##(47), 47, 48) # define MITK_PP_NODE_56(p) MITK_PP_IIF(p##(56), MITK_PP_NODE_52, MITK_PP_NODE_60) # define MITK_PP_NODE_52(p) MITK_PP_IIF(p##(52), MITK_PP_NODE_50, MITK_PP_NODE_54) # define MITK_PP_NODE_50(p) MITK_PP_IIF(p##(50), MITK_PP_NODE_49, MITK_PP_NODE_51) # define MITK_PP_NODE_49(p) MITK_PP_IIF(p##(49), 49, 50) # define MITK_PP_NODE_51(p) MITK_PP_IIF(p##(51), 51, 52) # define MITK_PP_NODE_54(p) MITK_PP_IIF(p##(54), MITK_PP_NODE_53, MITK_PP_NODE_55) # define MITK_PP_NODE_53(p) MITK_PP_IIF(p##(53), 53, 54) # define MITK_PP_NODE_55(p) MITK_PP_IIF(p##(55), 55, 56) # define MITK_PP_NODE_60(p) MITK_PP_IIF(p##(60), MITK_PP_NODE_58, MITK_PP_NODE_62) # define MITK_PP_NODE_58(p) MITK_PP_IIF(p##(58), MITK_PP_NODE_57, MITK_PP_NODE_59) # define MITK_PP_NODE_57(p) MITK_PP_IIF(p##(57), 57, 58) # define MITK_PP_NODE_59(p) MITK_PP_IIF(p##(59), 59, 60) # define MITK_PP_NODE_62(p) MITK_PP_IIF(p##(62), MITK_PP_NODE_61, MITK_PP_NODE_63) # define MITK_PP_NODE_61(p) MITK_PP_IIF(p##(61), 61, 62) # define MITK_PP_NODE_63(p) MITK_PP_IIF(p##(63), 63, 64) # define MITK_PP_NODE_96(p) MITK_PP_IIF(p##(96), MITK_PP_NODE_80, MITK_PP_NODE_112) # define MITK_PP_NODE_80(p) MITK_PP_IIF(p##(80), MITK_PP_NODE_72, MITK_PP_NODE_88) # define MITK_PP_NODE_72(p) MITK_PP_IIF(p##(72), MITK_PP_NODE_68, MITK_PP_NODE_76) # define MITK_PP_NODE_68(p) MITK_PP_IIF(p##(68), MITK_PP_NODE_66, MITK_PP_NODE_70) # define MITK_PP_NODE_66(p) MITK_PP_IIF(p##(66), MITK_PP_NODE_65, MITK_PP_NODE_67) # define MITK_PP_NODE_65(p) MITK_PP_IIF(p##(65), 65, 66) # define MITK_PP_NODE_67(p) MITK_PP_IIF(p##(67), 67, 68) # define MITK_PP_NODE_70(p) MITK_PP_IIF(p##(70), MITK_PP_NODE_69, MITK_PP_NODE_71) # define MITK_PP_NODE_69(p) MITK_PP_IIF(p##(69), 69, 70) # define MITK_PP_NODE_71(p) MITK_PP_IIF(p##(71), 71, 72) # define MITK_PP_NODE_76(p) MITK_PP_IIF(p##(76), MITK_PP_NODE_74, MITK_PP_NODE_78) # define MITK_PP_NODE_74(p) MITK_PP_IIF(p##(74), MITK_PP_NODE_73, MITK_PP_NODE_75) # define MITK_PP_NODE_73(p) MITK_PP_IIF(p##(73), 73, 74) # define MITK_PP_NODE_75(p) MITK_PP_IIF(p##(75), 75, 76) # define MITK_PP_NODE_78(p) MITK_PP_IIF(p##(78), MITK_PP_NODE_77, MITK_PP_NODE_79) # define MITK_PP_NODE_77(p) MITK_PP_IIF(p##(77), 77, 78) # define MITK_PP_NODE_79(p) MITK_PP_IIF(p##(79), 79, 80) # define MITK_PP_NODE_88(p) MITK_PP_IIF(p##(88), MITK_PP_NODE_84, MITK_PP_NODE_92) # define MITK_PP_NODE_84(p) MITK_PP_IIF(p##(84), MITK_PP_NODE_82, MITK_PP_NODE_86) # define MITK_PP_NODE_82(p) MITK_PP_IIF(p##(82), MITK_PP_NODE_81, MITK_PP_NODE_83) # define MITK_PP_NODE_81(p) MITK_PP_IIF(p##(81), 81, 82) # define MITK_PP_NODE_83(p) MITK_PP_IIF(p##(83), 83, 84) # define MITK_PP_NODE_86(p) MITK_PP_IIF(p##(86), MITK_PP_NODE_85, MITK_PP_NODE_87) # define MITK_PP_NODE_85(p) MITK_PP_IIF(p##(85), 85, 86) # define MITK_PP_NODE_87(p) MITK_PP_IIF(p##(87), 87, 88) # define MITK_PP_NODE_92(p) MITK_PP_IIF(p##(92), MITK_PP_NODE_90, MITK_PP_NODE_94) # define MITK_PP_NODE_90(p) MITK_PP_IIF(p##(90), MITK_PP_NODE_89, MITK_PP_NODE_91) # define MITK_PP_NODE_89(p) MITK_PP_IIF(p##(89), 89, 90) # define MITK_PP_NODE_91(p) MITK_PP_IIF(p##(91), 91, 92) # define MITK_PP_NODE_94(p) MITK_PP_IIF(p##(94), MITK_PP_NODE_93, MITK_PP_NODE_95) # define MITK_PP_NODE_93(p) MITK_PP_IIF(p##(93), 93, 94) # define MITK_PP_NODE_95(p) MITK_PP_IIF(p##(95), 95, 96) # define MITK_PP_NODE_112(p) MITK_PP_IIF(p##(112), MITK_PP_NODE_104, MITK_PP_NODE_120) # define MITK_PP_NODE_104(p) MITK_PP_IIF(p##(104), MITK_PP_NODE_100, MITK_PP_NODE_108) # define MITK_PP_NODE_100(p) MITK_PP_IIF(p##(100), MITK_PP_NODE_98, MITK_PP_NODE_102) # define MITK_PP_NODE_98(p) MITK_PP_IIF(p##(98), MITK_PP_NODE_97, MITK_PP_NODE_99) # define MITK_PP_NODE_97(p) MITK_PP_IIF(p##(97), 97, 98) # define MITK_PP_NODE_99(p) MITK_PP_IIF(p##(99), 99, 100) # define MITK_PP_NODE_102(p) MITK_PP_IIF(p##(102), MITK_PP_NODE_101, MITK_PP_NODE_103) # define MITK_PP_NODE_101(p) MITK_PP_IIF(p##(101), 101, 102) # define MITK_PP_NODE_103(p) MITK_PP_IIF(p##(103), 103, 104) # define MITK_PP_NODE_108(p) MITK_PP_IIF(p##(108), MITK_PP_NODE_106, MITK_PP_NODE_110) # define MITK_PP_NODE_106(p) MITK_PP_IIF(p##(106), MITK_PP_NODE_105, MITK_PP_NODE_107) # define MITK_PP_NODE_105(p) MITK_PP_IIF(p##(105), 105, 106) # define MITK_PP_NODE_107(p) MITK_PP_IIF(p##(107), 107, 108) # define MITK_PP_NODE_110(p) MITK_PP_IIF(p##(110), MITK_PP_NODE_109, MITK_PP_NODE_111) # define MITK_PP_NODE_109(p) MITK_PP_IIF(p##(109), 109, 110) # define MITK_PP_NODE_111(p) MITK_PP_IIF(p##(111), 111, 112) # define MITK_PP_NODE_120(p) MITK_PP_IIF(p##(120), MITK_PP_NODE_116, MITK_PP_NODE_124) # define MITK_PP_NODE_116(p) MITK_PP_IIF(p##(116), MITK_PP_NODE_114, MITK_PP_NODE_118) # define MITK_PP_NODE_114(p) MITK_PP_IIF(p##(114), MITK_PP_NODE_113, MITK_PP_NODE_115) # define MITK_PP_NODE_113(p) MITK_PP_IIF(p##(113), 113, 114) # define MITK_PP_NODE_115(p) MITK_PP_IIF(p##(115), 115, 116) # define MITK_PP_NODE_118(p) MITK_PP_IIF(p##(118), MITK_PP_NODE_117, MITK_PP_NODE_119) # define MITK_PP_NODE_117(p) MITK_PP_IIF(p##(117), 117, 118) # define MITK_PP_NODE_119(p) MITK_PP_IIF(p##(119), 119, 120) # define MITK_PP_NODE_124(p) MITK_PP_IIF(p##(124), MITK_PP_NODE_122, MITK_PP_NODE_126) # define MITK_PP_NODE_122(p) MITK_PP_IIF(p##(122), MITK_PP_NODE_121, MITK_PP_NODE_123) # define MITK_PP_NODE_121(p) MITK_PP_IIF(p##(121), 121, 122) # define MITK_PP_NODE_123(p) MITK_PP_IIF(p##(123), 123, 124) # define MITK_PP_NODE_126(p) MITK_PP_IIF(p##(126), MITK_PP_NODE_125, MITK_PP_NODE_127) # define MITK_PP_NODE_125(p) MITK_PP_IIF(p##(125), 125, 126) # define MITK_PP_NODE_127(p) MITK_PP_IIF(p##(127), 127, 128) # define MITK_PP_NODE_192(p) MITK_PP_IIF(p##(192), MITK_PP_NODE_160, MITK_PP_NODE_224) # define MITK_PP_NODE_160(p) MITK_PP_IIF(p##(160), MITK_PP_NODE_144, MITK_PP_NODE_176) # define MITK_PP_NODE_144(p) MITK_PP_IIF(p##(144), MITK_PP_NODE_136, MITK_PP_NODE_152) # define MITK_PP_NODE_136(p) MITK_PP_IIF(p##(136), MITK_PP_NODE_132, MITK_PP_NODE_140) # define MITK_PP_NODE_132(p) MITK_PP_IIF(p##(132), MITK_PP_NODE_130, MITK_PP_NODE_134) # define MITK_PP_NODE_130(p) MITK_PP_IIF(p##(130), MITK_PP_NODE_129, MITK_PP_NODE_131) # define MITK_PP_NODE_129(p) MITK_PP_IIF(p##(129), 129, 130) # define MITK_PP_NODE_131(p) MITK_PP_IIF(p##(131), 131, 132) # define MITK_PP_NODE_134(p) MITK_PP_IIF(p##(134), MITK_PP_NODE_133, MITK_PP_NODE_135) # define MITK_PP_NODE_133(p) MITK_PP_IIF(p##(133), 133, 134) # define MITK_PP_NODE_135(p) MITK_PP_IIF(p##(135), 135, 136) # define MITK_PP_NODE_140(p) MITK_PP_IIF(p##(140), MITK_PP_NODE_138, MITK_PP_NODE_142) # define MITK_PP_NODE_138(p) MITK_PP_IIF(p##(138), MITK_PP_NODE_137, MITK_PP_NODE_139) # define MITK_PP_NODE_137(p) MITK_PP_IIF(p##(137), 137, 138) # define MITK_PP_NODE_139(p) MITK_PP_IIF(p##(139), 139, 140) # define MITK_PP_NODE_142(p) MITK_PP_IIF(p##(142), MITK_PP_NODE_141, MITK_PP_NODE_143) # define MITK_PP_NODE_141(p) MITK_PP_IIF(p##(141), 141, 142) # define MITK_PP_NODE_143(p) MITK_PP_IIF(p##(143), 143, 144) # define MITK_PP_NODE_152(p) MITK_PP_IIF(p##(152), MITK_PP_NODE_148, MITK_PP_NODE_156) # define MITK_PP_NODE_148(p) MITK_PP_IIF(p##(148), MITK_PP_NODE_146, MITK_PP_NODE_150) # define MITK_PP_NODE_146(p) MITK_PP_IIF(p##(146), MITK_PP_NODE_145, MITK_PP_NODE_147) # define MITK_PP_NODE_145(p) MITK_PP_IIF(p##(145), 145, 146) # define MITK_PP_NODE_147(p) MITK_PP_IIF(p##(147), 147, 148) # define MITK_PP_NODE_150(p) MITK_PP_IIF(p##(150), MITK_PP_NODE_149, MITK_PP_NODE_151) # define MITK_PP_NODE_149(p) MITK_PP_IIF(p##(149), 149, 150) # define MITK_PP_NODE_151(p) MITK_PP_IIF(p##(151), 151, 152) # define MITK_PP_NODE_156(p) MITK_PP_IIF(p##(156), MITK_PP_NODE_154, MITK_PP_NODE_158) # define MITK_PP_NODE_154(p) MITK_PP_IIF(p##(154), MITK_PP_NODE_153, MITK_PP_NODE_155) # define MITK_PP_NODE_153(p) MITK_PP_IIF(p##(153), 153, 154) # define MITK_PP_NODE_155(p) MITK_PP_IIF(p##(155), 155, 156) # define MITK_PP_NODE_158(p) MITK_PP_IIF(p##(158), MITK_PP_NODE_157, MITK_PP_NODE_159) # define MITK_PP_NODE_157(p) MITK_PP_IIF(p##(157), 157, 158) # define MITK_PP_NODE_159(p) MITK_PP_IIF(p##(159), 159, 160) # define MITK_PP_NODE_176(p) MITK_PP_IIF(p##(176), MITK_PP_NODE_168, MITK_PP_NODE_184) # define MITK_PP_NODE_168(p) MITK_PP_IIF(p##(168), MITK_PP_NODE_164, MITK_PP_NODE_172) # define MITK_PP_NODE_164(p) MITK_PP_IIF(p##(164), MITK_PP_NODE_162, MITK_PP_NODE_166) # define MITK_PP_NODE_162(p) MITK_PP_IIF(p##(162), MITK_PP_NODE_161, MITK_PP_NODE_163) # define MITK_PP_NODE_161(p) MITK_PP_IIF(p##(161), 161, 162) # define MITK_PP_NODE_163(p) MITK_PP_IIF(p##(163), 163, 164) # define MITK_PP_NODE_166(p) MITK_PP_IIF(p##(166), MITK_PP_NODE_165, MITK_PP_NODE_167) # define MITK_PP_NODE_165(p) MITK_PP_IIF(p##(165), 165, 166) # define MITK_PP_NODE_167(p) MITK_PP_IIF(p##(167), 167, 168) # define MITK_PP_NODE_172(p) MITK_PP_IIF(p##(172), MITK_PP_NODE_170, MITK_PP_NODE_174) # define MITK_PP_NODE_170(p) MITK_PP_IIF(p##(170), MITK_PP_NODE_169, MITK_PP_NODE_171) # define MITK_PP_NODE_169(p) MITK_PP_IIF(p##(169), 169, 170) # define MITK_PP_NODE_171(p) MITK_PP_IIF(p##(171), 171, 172) # define MITK_PP_NODE_174(p) MITK_PP_IIF(p##(174), MITK_PP_NODE_173, MITK_PP_NODE_175) # define MITK_PP_NODE_173(p) MITK_PP_IIF(p##(173), 173, 174) # define MITK_PP_NODE_175(p) MITK_PP_IIF(p##(175), 175, 176) # define MITK_PP_NODE_184(p) MITK_PP_IIF(p##(184), MITK_PP_NODE_180, MITK_PP_NODE_188) # define MITK_PP_NODE_180(p) MITK_PP_IIF(p##(180), MITK_PP_NODE_178, MITK_PP_NODE_182) # define MITK_PP_NODE_178(p) MITK_PP_IIF(p##(178), MITK_PP_NODE_177, MITK_PP_NODE_179) # define MITK_PP_NODE_177(p) MITK_PP_IIF(p##(177), 177, 178) # define MITK_PP_NODE_179(p) MITK_PP_IIF(p##(179), 179, 180) # define MITK_PP_NODE_182(p) MITK_PP_IIF(p##(182), MITK_PP_NODE_181, MITK_PP_NODE_183) # define MITK_PP_NODE_181(p) MITK_PP_IIF(p##(181), 181, 182) # define MITK_PP_NODE_183(p) MITK_PP_IIF(p##(183), 183, 184) # define MITK_PP_NODE_188(p) MITK_PP_IIF(p##(188), MITK_PP_NODE_186, MITK_PP_NODE_190) # define MITK_PP_NODE_186(p) MITK_PP_IIF(p##(186), MITK_PP_NODE_185, MITK_PP_NODE_187) # define MITK_PP_NODE_185(p) MITK_PP_IIF(p##(185), 185, 186) # define MITK_PP_NODE_187(p) MITK_PP_IIF(p##(187), 187, 188) # define MITK_PP_NODE_190(p) MITK_PP_IIF(p##(190), MITK_PP_NODE_189, MITK_PP_NODE_191) # define MITK_PP_NODE_189(p) MITK_PP_IIF(p##(189), 189, 190) # define MITK_PP_NODE_191(p) MITK_PP_IIF(p##(191), 191, 192) # define MITK_PP_NODE_224(p) MITK_PP_IIF(p##(224), MITK_PP_NODE_208, MITK_PP_NODE_240) # define MITK_PP_NODE_208(p) MITK_PP_IIF(p##(208), MITK_PP_NODE_200, MITK_PP_NODE_216) # define MITK_PP_NODE_200(p) MITK_PP_IIF(p##(200), MITK_PP_NODE_196, MITK_PP_NODE_204) # define MITK_PP_NODE_196(p) MITK_PP_IIF(p##(196), MITK_PP_NODE_194, MITK_PP_NODE_198) # define MITK_PP_NODE_194(p) MITK_PP_IIF(p##(194), MITK_PP_NODE_193, MITK_PP_NODE_195) # define MITK_PP_NODE_193(p) MITK_PP_IIF(p##(193), 193, 194) # define MITK_PP_NODE_195(p) MITK_PP_IIF(p##(195), 195, 196) # define MITK_PP_NODE_198(p) MITK_PP_IIF(p##(198), MITK_PP_NODE_197, MITK_PP_NODE_199) # define MITK_PP_NODE_197(p) MITK_PP_IIF(p##(197), 197, 198) # define MITK_PP_NODE_199(p) MITK_PP_IIF(p##(199), 199, 200) # define MITK_PP_NODE_204(p) MITK_PP_IIF(p##(204), MITK_PP_NODE_202, MITK_PP_NODE_206) # define MITK_PP_NODE_202(p) MITK_PP_IIF(p##(202), MITK_PP_NODE_201, MITK_PP_NODE_203) # define MITK_PP_NODE_201(p) MITK_PP_IIF(p##(201), 201, 202) # define MITK_PP_NODE_203(p) MITK_PP_IIF(p##(203), 203, 204) # define MITK_PP_NODE_206(p) MITK_PP_IIF(p##(206), MITK_PP_NODE_205, MITK_PP_NODE_207) # define MITK_PP_NODE_205(p) MITK_PP_IIF(p##(205), 205, 206) # define MITK_PP_NODE_207(p) MITK_PP_IIF(p##(207), 207, 208) # define MITK_PP_NODE_216(p) MITK_PP_IIF(p##(216), MITK_PP_NODE_212, MITK_PP_NODE_220) # define MITK_PP_NODE_212(p) MITK_PP_IIF(p##(212), MITK_PP_NODE_210, MITK_PP_NODE_214) # define MITK_PP_NODE_210(p) MITK_PP_IIF(p##(210), MITK_PP_NODE_209, MITK_PP_NODE_211) # define MITK_PP_NODE_209(p) MITK_PP_IIF(p##(209), 209, 210) # define MITK_PP_NODE_211(p) MITK_PP_IIF(p##(211), 211, 212) # define MITK_PP_NODE_214(p) MITK_PP_IIF(p##(214), MITK_PP_NODE_213, MITK_PP_NODE_215) # define MITK_PP_NODE_213(p) MITK_PP_IIF(p##(213), 213, 214) # define MITK_PP_NODE_215(p) MITK_PP_IIF(p##(215), 215, 216) # define MITK_PP_NODE_220(p) MITK_PP_IIF(p##(220), MITK_PP_NODE_218, MITK_PP_NODE_222) # define MITK_PP_NODE_218(p) MITK_PP_IIF(p##(218), MITK_PP_NODE_217, MITK_PP_NODE_219) # define MITK_PP_NODE_217(p) MITK_PP_IIF(p##(217), 217, 218) # define MITK_PP_NODE_219(p) MITK_PP_IIF(p##(219), 219, 220) # define MITK_PP_NODE_222(p) MITK_PP_IIF(p##(222), MITK_PP_NODE_221, MITK_PP_NODE_223) # define MITK_PP_NODE_221(p) MITK_PP_IIF(p##(221), 221, 222) # define MITK_PP_NODE_223(p) MITK_PP_IIF(p##(223), 223, 224) # define MITK_PP_NODE_240(p) MITK_PP_IIF(p##(240), MITK_PP_NODE_232, MITK_PP_NODE_248) # define MITK_PP_NODE_232(p) MITK_PP_IIF(p##(232), MITK_PP_NODE_228, MITK_PP_NODE_236) # define MITK_PP_NODE_228(p) MITK_PP_IIF(p##(228), MITK_PP_NODE_226, MITK_PP_NODE_230) # define MITK_PP_NODE_226(p) MITK_PP_IIF(p##(226), MITK_PP_NODE_225, MITK_PP_NODE_227) # define MITK_PP_NODE_225(p) MITK_PP_IIF(p##(225), 225, 226) # define MITK_PP_NODE_227(p) MITK_PP_IIF(p##(227), 227, 228) # define MITK_PP_NODE_230(p) MITK_PP_IIF(p##(230), MITK_PP_NODE_229, MITK_PP_NODE_231) # define MITK_PP_NODE_229(p) MITK_PP_IIF(p##(229), 229, 230) # define MITK_PP_NODE_231(p) MITK_PP_IIF(p##(231), 231, 232) # define MITK_PP_NODE_236(p) MITK_PP_IIF(p##(236), MITK_PP_NODE_234, MITK_PP_NODE_238) # define MITK_PP_NODE_234(p) MITK_PP_IIF(p##(234), MITK_PP_NODE_233, MITK_PP_NODE_235) # define MITK_PP_NODE_233(p) MITK_PP_IIF(p##(233), 233, 234) # define MITK_PP_NODE_235(p) MITK_PP_IIF(p##(235), 235, 236) # define MITK_PP_NODE_238(p) MITK_PP_IIF(p##(238), MITK_PP_NODE_237, MITK_PP_NODE_239) # define MITK_PP_NODE_237(p) MITK_PP_IIF(p##(237), 237, 238) # define MITK_PP_NODE_239(p) MITK_PP_IIF(p##(239), 239, 240) # define MITK_PP_NODE_248(p) MITK_PP_IIF(p##(248), MITK_PP_NODE_244, MITK_PP_NODE_252) # define MITK_PP_NODE_244(p) MITK_PP_IIF(p##(244), MITK_PP_NODE_242, MITK_PP_NODE_246) # define MITK_PP_NODE_242(p) MITK_PP_IIF(p##(242), MITK_PP_NODE_241, MITK_PP_NODE_243) # define MITK_PP_NODE_241(p) MITK_PP_IIF(p##(241), 241, 242) # define MITK_PP_NODE_243(p) MITK_PP_IIF(p##(243), 243, 244) # define MITK_PP_NODE_246(p) MITK_PP_IIF(p##(246), MITK_PP_NODE_245, MITK_PP_NODE_247) # define MITK_PP_NODE_245(p) MITK_PP_IIF(p##(245), 245, 246) # define MITK_PP_NODE_247(p) MITK_PP_IIF(p##(247), 247, 248) # define MITK_PP_NODE_252(p) MITK_PP_IIF(p##(252), MITK_PP_NODE_250, MITK_PP_NODE_254) # define MITK_PP_NODE_250(p) MITK_PP_IIF(p##(250), MITK_PP_NODE_249, MITK_PP_NODE_251) # define MITK_PP_NODE_249(p) MITK_PP_IIF(p##(249), 249, 250) # define MITK_PP_NODE_251(p) MITK_PP_IIF(p##(251), 251, 252) # define MITK_PP_NODE_254(p) MITK_PP_IIF(p##(254), MITK_PP_NODE_253, MITK_PP_NODE_255) # define MITK_PP_NODE_253(p) MITK_PP_IIF(p##(253), 253, 254) # define MITK_PP_NODE_255(p) MITK_PP_IIF(p##(255), 255, 256) # # endif diff --git a/Core/Code/Algorithms/mitkPPExpand.h b/Core/Code/Algorithms/mitkPPExpand.h index 3d05a298b8..601dcb17a8 100644 --- a/Core/Code/Algorithms/mitkPPExpand.h +++ b/Core/Code/Algorithms/mitkPPExpand.h @@ -1,17 +1,32 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_EXPAND_HPP # define MITK_PREPROCESSOR_EXPAND_HPP # # include "mitkPPFacilitiesExpand.h" # # endif diff --git a/Core/Code/Algorithms/mitkPPFacilitiesEmpty.h b/Core/Code/Algorithms/mitkPPFacilitiesEmpty.h index 3cb10588ce..f9261f2076 100644 --- a/Core/Code/Algorithms/mitkPPFacilitiesEmpty.h +++ b/Core/Code/Algorithms/mitkPPFacilitiesEmpty.h @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_FACILITIES_EMPTY_HPP # define MITK_PREPROCESSOR_FACILITIES_EMPTY_HPP # # /* MITK_PP_EMPTY */ # # define MITK_PP_EMPTY() # # endif diff --git a/Core/Code/Algorithms/mitkPPFacilitiesExpand.h b/Core/Code/Algorithms/mitkPPFacilitiesExpand.h index f6f128160f..d91ac85ad6 100644 --- a/Core/Code/Algorithms/mitkPPFacilitiesExpand.h +++ b/Core/Code/Algorithms/mitkPPFacilitiesExpand.h @@ -1,28 +1,43 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_FACILITIES_EXPAND_HPP # define MITK_PREPROCESSOR_FACILITIES_EXPAND_HPP # # include "mitkPPConfig.h" # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() && ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_DMC() # define MITK_PP_EXPAND(x) MITK_PP_EXPAND_I(x) # else # define MITK_PP_EXPAND(x) MITK_PP_EXPAND_OO((x)) # define MITK_PP_EXPAND_OO(par) MITK_PP_EXPAND_I ## par # endif # # define MITK_PP_EXPAND_I(x) x # # endif diff --git a/Core/Code/Algorithms/mitkPPLogicalBool.h b/Core/Code/Algorithms/mitkPPLogicalBool.h index c69e4ae4f9..19cfcb8723 100644 --- a/Core/Code/Algorithms/mitkPPLogicalBool.h +++ b/Core/Code/Algorithms/mitkPPLogicalBool.h @@ -1,288 +1,303 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_LOGICAL_BOOL_HPP # define MITK_PREPROCESSOR_LOGICAL_BOOL_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_BOOL */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_BOOL(x) MITK_PP_BOOL_I(x) # else # define MITK_PP_BOOL(x) MITK_PP_BOOL_OO((x)) # define MITK_PP_BOOL_OO(par) MITK_PP_BOOL_I ## par # endif # # define MITK_PP_BOOL_I(x) MITK_PP_BOOL_ ## x # # define MITK_PP_BOOL_0 0 # define MITK_PP_BOOL_1 1 # define MITK_PP_BOOL_2 1 # define MITK_PP_BOOL_3 1 # define MITK_PP_BOOL_4 1 # define MITK_PP_BOOL_5 1 # define MITK_PP_BOOL_6 1 # define MITK_PP_BOOL_7 1 # define MITK_PP_BOOL_8 1 # define MITK_PP_BOOL_9 1 # define MITK_PP_BOOL_10 1 # define MITK_PP_BOOL_11 1 # define MITK_PP_BOOL_12 1 # define MITK_PP_BOOL_13 1 # define MITK_PP_BOOL_14 1 # define MITK_PP_BOOL_15 1 # define MITK_PP_BOOL_16 1 # define MITK_PP_BOOL_17 1 # define MITK_PP_BOOL_18 1 # define MITK_PP_BOOL_19 1 # define MITK_PP_BOOL_20 1 # define MITK_PP_BOOL_21 1 # define MITK_PP_BOOL_22 1 # define MITK_PP_BOOL_23 1 # define MITK_PP_BOOL_24 1 # define MITK_PP_BOOL_25 1 # define MITK_PP_BOOL_26 1 # define MITK_PP_BOOL_27 1 # define MITK_PP_BOOL_28 1 # define MITK_PP_BOOL_29 1 # define MITK_PP_BOOL_30 1 # define MITK_PP_BOOL_31 1 # define MITK_PP_BOOL_32 1 # define MITK_PP_BOOL_33 1 # define MITK_PP_BOOL_34 1 # define MITK_PP_BOOL_35 1 # define MITK_PP_BOOL_36 1 # define MITK_PP_BOOL_37 1 # define MITK_PP_BOOL_38 1 # define MITK_PP_BOOL_39 1 # define MITK_PP_BOOL_40 1 # define MITK_PP_BOOL_41 1 # define MITK_PP_BOOL_42 1 # define MITK_PP_BOOL_43 1 # define MITK_PP_BOOL_44 1 # define MITK_PP_BOOL_45 1 # define MITK_PP_BOOL_46 1 # define MITK_PP_BOOL_47 1 # define MITK_PP_BOOL_48 1 # define MITK_PP_BOOL_49 1 # define MITK_PP_BOOL_50 1 # define MITK_PP_BOOL_51 1 # define MITK_PP_BOOL_52 1 # define MITK_PP_BOOL_53 1 # define MITK_PP_BOOL_54 1 # define MITK_PP_BOOL_55 1 # define MITK_PP_BOOL_56 1 # define MITK_PP_BOOL_57 1 # define MITK_PP_BOOL_58 1 # define MITK_PP_BOOL_59 1 # define MITK_PP_BOOL_60 1 # define MITK_PP_BOOL_61 1 # define MITK_PP_BOOL_62 1 # define MITK_PP_BOOL_63 1 # define MITK_PP_BOOL_64 1 # define MITK_PP_BOOL_65 1 # define MITK_PP_BOOL_66 1 # define MITK_PP_BOOL_67 1 # define MITK_PP_BOOL_68 1 # define MITK_PP_BOOL_69 1 # define MITK_PP_BOOL_70 1 # define MITK_PP_BOOL_71 1 # define MITK_PP_BOOL_72 1 # define MITK_PP_BOOL_73 1 # define MITK_PP_BOOL_74 1 # define MITK_PP_BOOL_75 1 # define MITK_PP_BOOL_76 1 # define MITK_PP_BOOL_77 1 # define MITK_PP_BOOL_78 1 # define MITK_PP_BOOL_79 1 # define MITK_PP_BOOL_80 1 # define MITK_PP_BOOL_81 1 # define MITK_PP_BOOL_82 1 # define MITK_PP_BOOL_83 1 # define MITK_PP_BOOL_84 1 # define MITK_PP_BOOL_85 1 # define MITK_PP_BOOL_86 1 # define MITK_PP_BOOL_87 1 # define MITK_PP_BOOL_88 1 # define MITK_PP_BOOL_89 1 # define MITK_PP_BOOL_90 1 # define MITK_PP_BOOL_91 1 # define MITK_PP_BOOL_92 1 # define MITK_PP_BOOL_93 1 # define MITK_PP_BOOL_94 1 # define MITK_PP_BOOL_95 1 # define MITK_PP_BOOL_96 1 # define MITK_PP_BOOL_97 1 # define MITK_PP_BOOL_98 1 # define MITK_PP_BOOL_99 1 # define MITK_PP_BOOL_100 1 # define MITK_PP_BOOL_101 1 # define MITK_PP_BOOL_102 1 # define MITK_PP_BOOL_103 1 # define MITK_PP_BOOL_104 1 # define MITK_PP_BOOL_105 1 # define MITK_PP_BOOL_106 1 # define MITK_PP_BOOL_107 1 # define MITK_PP_BOOL_108 1 # define MITK_PP_BOOL_109 1 # define MITK_PP_BOOL_110 1 # define MITK_PP_BOOL_111 1 # define MITK_PP_BOOL_112 1 # define MITK_PP_BOOL_113 1 # define MITK_PP_BOOL_114 1 # define MITK_PP_BOOL_115 1 # define MITK_PP_BOOL_116 1 # define MITK_PP_BOOL_117 1 # define MITK_PP_BOOL_118 1 # define MITK_PP_BOOL_119 1 # define MITK_PP_BOOL_120 1 # define MITK_PP_BOOL_121 1 # define MITK_PP_BOOL_122 1 # define MITK_PP_BOOL_123 1 # define MITK_PP_BOOL_124 1 # define MITK_PP_BOOL_125 1 # define MITK_PP_BOOL_126 1 # define MITK_PP_BOOL_127 1 # define MITK_PP_BOOL_128 1 # define MITK_PP_BOOL_129 1 # define MITK_PP_BOOL_130 1 # define MITK_PP_BOOL_131 1 # define MITK_PP_BOOL_132 1 # define MITK_PP_BOOL_133 1 # define MITK_PP_BOOL_134 1 # define MITK_PP_BOOL_135 1 # define MITK_PP_BOOL_136 1 # define MITK_PP_BOOL_137 1 # define MITK_PP_BOOL_138 1 # define MITK_PP_BOOL_139 1 # define MITK_PP_BOOL_140 1 # define MITK_PP_BOOL_141 1 # define MITK_PP_BOOL_142 1 # define MITK_PP_BOOL_143 1 # define MITK_PP_BOOL_144 1 # define MITK_PP_BOOL_145 1 # define MITK_PP_BOOL_146 1 # define MITK_PP_BOOL_147 1 # define MITK_PP_BOOL_148 1 # define MITK_PP_BOOL_149 1 # define MITK_PP_BOOL_150 1 # define MITK_PP_BOOL_151 1 # define MITK_PP_BOOL_152 1 # define MITK_PP_BOOL_153 1 # define MITK_PP_BOOL_154 1 # define MITK_PP_BOOL_155 1 # define MITK_PP_BOOL_156 1 # define MITK_PP_BOOL_157 1 # define MITK_PP_BOOL_158 1 # define MITK_PP_BOOL_159 1 # define MITK_PP_BOOL_160 1 # define MITK_PP_BOOL_161 1 # define MITK_PP_BOOL_162 1 # define MITK_PP_BOOL_163 1 # define MITK_PP_BOOL_164 1 # define MITK_PP_BOOL_165 1 # define MITK_PP_BOOL_166 1 # define MITK_PP_BOOL_167 1 # define MITK_PP_BOOL_168 1 # define MITK_PP_BOOL_169 1 # define MITK_PP_BOOL_170 1 # define MITK_PP_BOOL_171 1 # define MITK_PP_BOOL_172 1 # define MITK_PP_BOOL_173 1 # define MITK_PP_BOOL_174 1 # define MITK_PP_BOOL_175 1 # define MITK_PP_BOOL_176 1 # define MITK_PP_BOOL_177 1 # define MITK_PP_BOOL_178 1 # define MITK_PP_BOOL_179 1 # define MITK_PP_BOOL_180 1 # define MITK_PP_BOOL_181 1 # define MITK_PP_BOOL_182 1 # define MITK_PP_BOOL_183 1 # define MITK_PP_BOOL_184 1 # define MITK_PP_BOOL_185 1 # define MITK_PP_BOOL_186 1 # define MITK_PP_BOOL_187 1 # define MITK_PP_BOOL_188 1 # define MITK_PP_BOOL_189 1 # define MITK_PP_BOOL_190 1 # define MITK_PP_BOOL_191 1 # define MITK_PP_BOOL_192 1 # define MITK_PP_BOOL_193 1 # define MITK_PP_BOOL_194 1 # define MITK_PP_BOOL_195 1 # define MITK_PP_BOOL_196 1 # define MITK_PP_BOOL_197 1 # define MITK_PP_BOOL_198 1 # define MITK_PP_BOOL_199 1 # define MITK_PP_BOOL_200 1 # define MITK_PP_BOOL_201 1 # define MITK_PP_BOOL_202 1 # define MITK_PP_BOOL_203 1 # define MITK_PP_BOOL_204 1 # define MITK_PP_BOOL_205 1 # define MITK_PP_BOOL_206 1 # define MITK_PP_BOOL_207 1 # define MITK_PP_BOOL_208 1 # define MITK_PP_BOOL_209 1 # define MITK_PP_BOOL_210 1 # define MITK_PP_BOOL_211 1 # define MITK_PP_BOOL_212 1 # define MITK_PP_BOOL_213 1 # define MITK_PP_BOOL_214 1 # define MITK_PP_BOOL_215 1 # define MITK_PP_BOOL_216 1 # define MITK_PP_BOOL_217 1 # define MITK_PP_BOOL_218 1 # define MITK_PP_BOOL_219 1 # define MITK_PP_BOOL_220 1 # define MITK_PP_BOOL_221 1 # define MITK_PP_BOOL_222 1 # define MITK_PP_BOOL_223 1 # define MITK_PP_BOOL_224 1 # define MITK_PP_BOOL_225 1 # define MITK_PP_BOOL_226 1 # define MITK_PP_BOOL_227 1 # define MITK_PP_BOOL_228 1 # define MITK_PP_BOOL_229 1 # define MITK_PP_BOOL_230 1 # define MITK_PP_BOOL_231 1 # define MITK_PP_BOOL_232 1 # define MITK_PP_BOOL_233 1 # define MITK_PP_BOOL_234 1 # define MITK_PP_BOOL_235 1 # define MITK_PP_BOOL_236 1 # define MITK_PP_BOOL_237 1 # define MITK_PP_BOOL_238 1 # define MITK_PP_BOOL_239 1 # define MITK_PP_BOOL_240 1 # define MITK_PP_BOOL_241 1 # define MITK_PP_BOOL_242 1 # define MITK_PP_BOOL_243 1 # define MITK_PP_BOOL_244 1 # define MITK_PP_BOOL_245 1 # define MITK_PP_BOOL_246 1 # define MITK_PP_BOOL_247 1 # define MITK_PP_BOOL_248 1 # define MITK_PP_BOOL_249 1 # define MITK_PP_BOOL_250 1 # define MITK_PP_BOOL_251 1 # define MITK_PP_BOOL_252 1 # define MITK_PP_BOOL_253 1 # define MITK_PP_BOOL_254 1 # define MITK_PP_BOOL_255 1 # define MITK_PP_BOOL_256 1 # # endif diff --git a/Core/Code/Algorithms/mitkPPRepetitionDetailDMCFor.h b/Core/Code/Algorithms/mitkPPRepetitionDetailDMCFor.h index 1d80d7fd02..28c832973a 100644 --- a/Core/Code/Algorithms/mitkPPRepetitionDetailDMCFor.h +++ b/Core/Code/Algorithms/mitkPPRepetitionDetailDMCFor.h @@ -1,536 +1,551 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP # define MITK_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP # # include "mitkPPControlExprIIf.h" # include "mitkPPControlIIf.h" # include "mitkPPLogicalBool.h" # include "mitkPPTupleEat.h" # # define MITK_PP_FOR_1(s, p, o, m) MITK_PP_FOR_1_C(MITK_PP_BOOL(p##(2, s)), s, p, o, m) # define MITK_PP_FOR_2(s, p, o, m) MITK_PP_FOR_2_C(MITK_PP_BOOL(p##(3, s)), s, p, o, m) # define MITK_PP_FOR_3(s, p, o, m) MITK_PP_FOR_3_C(MITK_PP_BOOL(p##(4, s)), s, p, o, m) # define MITK_PP_FOR_4(s, p, o, m) MITK_PP_FOR_4_C(MITK_PP_BOOL(p##(5, s)), s, p, o, m) # define MITK_PP_FOR_5(s, p, o, m) MITK_PP_FOR_5_C(MITK_PP_BOOL(p##(6, s)), s, p, o, m) # define MITK_PP_FOR_6(s, p, o, m) MITK_PP_FOR_6_C(MITK_PP_BOOL(p##(7, s)), s, p, o, m) # define MITK_PP_FOR_7(s, p, o, m) MITK_PP_FOR_7_C(MITK_PP_BOOL(p##(8, s)), s, p, o, m) # define MITK_PP_FOR_8(s, p, o, m) MITK_PP_FOR_8_C(MITK_PP_BOOL(p##(9, s)), s, p, o, m) # define MITK_PP_FOR_9(s, p, o, m) MITK_PP_FOR_9_C(MITK_PP_BOOL(p##(10, s)), s, p, o, m) # define MITK_PP_FOR_10(s, p, o, m) MITK_PP_FOR_10_C(MITK_PP_BOOL(p##(11, s)), s, p, o, m) # define MITK_PP_FOR_11(s, p, o, m) MITK_PP_FOR_11_C(MITK_PP_BOOL(p##(12, s)), s, p, o, m) # define MITK_PP_FOR_12(s, p, o, m) MITK_PP_FOR_12_C(MITK_PP_BOOL(p##(13, s)), s, p, o, m) # define MITK_PP_FOR_13(s, p, o, m) MITK_PP_FOR_13_C(MITK_PP_BOOL(p##(14, s)), s, p, o, m) # define MITK_PP_FOR_14(s, p, o, m) MITK_PP_FOR_14_C(MITK_PP_BOOL(p##(15, s)), s, p, o, m) # define MITK_PP_FOR_15(s, p, o, m) MITK_PP_FOR_15_C(MITK_PP_BOOL(p##(16, s)), s, p, o, m) # define MITK_PP_FOR_16(s, p, o, m) MITK_PP_FOR_16_C(MITK_PP_BOOL(p##(17, s)), s, p, o, m) # define MITK_PP_FOR_17(s, p, o, m) MITK_PP_FOR_17_C(MITK_PP_BOOL(p##(18, s)), s, p, o, m) # define MITK_PP_FOR_18(s, p, o, m) MITK_PP_FOR_18_C(MITK_PP_BOOL(p##(19, s)), s, p, o, m) # define MITK_PP_FOR_19(s, p, o, m) MITK_PP_FOR_19_C(MITK_PP_BOOL(p##(20, s)), s, p, o, m) # define MITK_PP_FOR_20(s, p, o, m) MITK_PP_FOR_20_C(MITK_PP_BOOL(p##(21, s)), s, p, o, m) # define MITK_PP_FOR_21(s, p, o, m) MITK_PP_FOR_21_C(MITK_PP_BOOL(p##(22, s)), s, p, o, m) # define MITK_PP_FOR_22(s, p, o, m) MITK_PP_FOR_22_C(MITK_PP_BOOL(p##(23, s)), s, p, o, m) # define MITK_PP_FOR_23(s, p, o, m) MITK_PP_FOR_23_C(MITK_PP_BOOL(p##(24, s)), s, p, o, m) # define MITK_PP_FOR_24(s, p, o, m) MITK_PP_FOR_24_C(MITK_PP_BOOL(p##(25, s)), s, p, o, m) # define MITK_PP_FOR_25(s, p, o, m) MITK_PP_FOR_25_C(MITK_PP_BOOL(p##(26, s)), s, p, o, m) # define MITK_PP_FOR_26(s, p, o, m) MITK_PP_FOR_26_C(MITK_PP_BOOL(p##(27, s)), s, p, o, m) # define MITK_PP_FOR_27(s, p, o, m) MITK_PP_FOR_27_C(MITK_PP_BOOL(p##(28, s)), s, p, o, m) # define MITK_PP_FOR_28(s, p, o, m) MITK_PP_FOR_28_C(MITK_PP_BOOL(p##(29, s)), s, p, o, m) # define MITK_PP_FOR_29(s, p, o, m) MITK_PP_FOR_29_C(MITK_PP_BOOL(p##(30, s)), s, p, o, m) # define MITK_PP_FOR_30(s, p, o, m) MITK_PP_FOR_30_C(MITK_PP_BOOL(p##(31, s)), s, p, o, m) # define MITK_PP_FOR_31(s, p, o, m) MITK_PP_FOR_31_C(MITK_PP_BOOL(p##(32, s)), s, p, o, m) # define MITK_PP_FOR_32(s, p, o, m) MITK_PP_FOR_32_C(MITK_PP_BOOL(p##(33, s)), s, p, o, m) # define MITK_PP_FOR_33(s, p, o, m) MITK_PP_FOR_33_C(MITK_PP_BOOL(p##(34, s)), s, p, o, m) # define MITK_PP_FOR_34(s, p, o, m) MITK_PP_FOR_34_C(MITK_PP_BOOL(p##(35, s)), s, p, o, m) # define MITK_PP_FOR_35(s, p, o, m) MITK_PP_FOR_35_C(MITK_PP_BOOL(p##(36, s)), s, p, o, m) # define MITK_PP_FOR_36(s, p, o, m) MITK_PP_FOR_36_C(MITK_PP_BOOL(p##(37, s)), s, p, o, m) # define MITK_PP_FOR_37(s, p, o, m) MITK_PP_FOR_37_C(MITK_PP_BOOL(p##(38, s)), s, p, o, m) # define MITK_PP_FOR_38(s, p, o, m) MITK_PP_FOR_38_C(MITK_PP_BOOL(p##(39, s)), s, p, o, m) # define MITK_PP_FOR_39(s, p, o, m) MITK_PP_FOR_39_C(MITK_PP_BOOL(p##(40, s)), s, p, o, m) # define MITK_PP_FOR_40(s, p, o, m) MITK_PP_FOR_40_C(MITK_PP_BOOL(p##(41, s)), s, p, o, m) # define MITK_PP_FOR_41(s, p, o, m) MITK_PP_FOR_41_C(MITK_PP_BOOL(p##(42, s)), s, p, o, m) # define MITK_PP_FOR_42(s, p, o, m) MITK_PP_FOR_42_C(MITK_PP_BOOL(p##(43, s)), s, p, o, m) # define MITK_PP_FOR_43(s, p, o, m) MITK_PP_FOR_43_C(MITK_PP_BOOL(p##(44, s)), s, p, o, m) # define MITK_PP_FOR_44(s, p, o, m) MITK_PP_FOR_44_C(MITK_PP_BOOL(p##(45, s)), s, p, o, m) # define MITK_PP_FOR_45(s, p, o, m) MITK_PP_FOR_45_C(MITK_PP_BOOL(p##(46, s)), s, p, o, m) # define MITK_PP_FOR_46(s, p, o, m) MITK_PP_FOR_46_C(MITK_PP_BOOL(p##(47, s)), s, p, o, m) # define MITK_PP_FOR_47(s, p, o, m) MITK_PP_FOR_47_C(MITK_PP_BOOL(p##(48, s)), s, p, o, m) # define MITK_PP_FOR_48(s, p, o, m) MITK_PP_FOR_48_C(MITK_PP_BOOL(p##(49, s)), s, p, o, m) # define MITK_PP_FOR_49(s, p, o, m) MITK_PP_FOR_49_C(MITK_PP_BOOL(p##(50, s)), s, p, o, m) # define MITK_PP_FOR_50(s, p, o, m) MITK_PP_FOR_50_C(MITK_PP_BOOL(p##(51, s)), s, p, o, m) # define MITK_PP_FOR_51(s, p, o, m) MITK_PP_FOR_51_C(MITK_PP_BOOL(p##(52, s)), s, p, o, m) # define MITK_PP_FOR_52(s, p, o, m) MITK_PP_FOR_52_C(MITK_PP_BOOL(p##(53, s)), s, p, o, m) # define MITK_PP_FOR_53(s, p, o, m) MITK_PP_FOR_53_C(MITK_PP_BOOL(p##(54, s)), s, p, o, m) # define MITK_PP_FOR_54(s, p, o, m) MITK_PP_FOR_54_C(MITK_PP_BOOL(p##(55, s)), s, p, o, m) # define MITK_PP_FOR_55(s, p, o, m) MITK_PP_FOR_55_C(MITK_PP_BOOL(p##(56, s)), s, p, o, m) # define MITK_PP_FOR_56(s, p, o, m) MITK_PP_FOR_56_C(MITK_PP_BOOL(p##(57, s)), s, p, o, m) # define MITK_PP_FOR_57(s, p, o, m) MITK_PP_FOR_57_C(MITK_PP_BOOL(p##(58, s)), s, p, o, m) # define MITK_PP_FOR_58(s, p, o, m) MITK_PP_FOR_58_C(MITK_PP_BOOL(p##(59, s)), s, p, o, m) # define MITK_PP_FOR_59(s, p, o, m) MITK_PP_FOR_59_C(MITK_PP_BOOL(p##(60, s)), s, p, o, m) # define MITK_PP_FOR_60(s, p, o, m) MITK_PP_FOR_60_C(MITK_PP_BOOL(p##(61, s)), s, p, o, m) # define MITK_PP_FOR_61(s, p, o, m) MITK_PP_FOR_61_C(MITK_PP_BOOL(p##(62, s)), s, p, o, m) # define MITK_PP_FOR_62(s, p, o, m) MITK_PP_FOR_62_C(MITK_PP_BOOL(p##(63, s)), s, p, o, m) # define MITK_PP_FOR_63(s, p, o, m) MITK_PP_FOR_63_C(MITK_PP_BOOL(p##(64, s)), s, p, o, m) # define MITK_PP_FOR_64(s, p, o, m) MITK_PP_FOR_64_C(MITK_PP_BOOL(p##(65, s)), s, p, o, m) # define MITK_PP_FOR_65(s, p, o, m) MITK_PP_FOR_65_C(MITK_PP_BOOL(p##(66, s)), s, p, o, m) # define MITK_PP_FOR_66(s, p, o, m) MITK_PP_FOR_66_C(MITK_PP_BOOL(p##(67, s)), s, p, o, m) # define MITK_PP_FOR_67(s, p, o, m) MITK_PP_FOR_67_C(MITK_PP_BOOL(p##(68, s)), s, p, o, m) # define MITK_PP_FOR_68(s, p, o, m) MITK_PP_FOR_68_C(MITK_PP_BOOL(p##(69, s)), s, p, o, m) # define MITK_PP_FOR_69(s, p, o, m) MITK_PP_FOR_69_C(MITK_PP_BOOL(p##(70, s)), s, p, o, m) # define MITK_PP_FOR_70(s, p, o, m) MITK_PP_FOR_70_C(MITK_PP_BOOL(p##(71, s)), s, p, o, m) # define MITK_PP_FOR_71(s, p, o, m) MITK_PP_FOR_71_C(MITK_PP_BOOL(p##(72, s)), s, p, o, m) # define MITK_PP_FOR_72(s, p, o, m) MITK_PP_FOR_72_C(MITK_PP_BOOL(p##(73, s)), s, p, o, m) # define MITK_PP_FOR_73(s, p, o, m) MITK_PP_FOR_73_C(MITK_PP_BOOL(p##(74, s)), s, p, o, m) # define MITK_PP_FOR_74(s, p, o, m) MITK_PP_FOR_74_C(MITK_PP_BOOL(p##(75, s)), s, p, o, m) # define MITK_PP_FOR_75(s, p, o, m) MITK_PP_FOR_75_C(MITK_PP_BOOL(p##(76, s)), s, p, o, m) # define MITK_PP_FOR_76(s, p, o, m) MITK_PP_FOR_76_C(MITK_PP_BOOL(p##(77, s)), s, p, o, m) # define MITK_PP_FOR_77(s, p, o, m) MITK_PP_FOR_77_C(MITK_PP_BOOL(p##(78, s)), s, p, o, m) # define MITK_PP_FOR_78(s, p, o, m) MITK_PP_FOR_78_C(MITK_PP_BOOL(p##(79, s)), s, p, o, m) # define MITK_PP_FOR_79(s, p, o, m) MITK_PP_FOR_79_C(MITK_PP_BOOL(p##(80, s)), s, p, o, m) # define MITK_PP_FOR_80(s, p, o, m) MITK_PP_FOR_80_C(MITK_PP_BOOL(p##(81, s)), s, p, o, m) # define MITK_PP_FOR_81(s, p, o, m) MITK_PP_FOR_81_C(MITK_PP_BOOL(p##(82, s)), s, p, o, m) # define MITK_PP_FOR_82(s, p, o, m) MITK_PP_FOR_82_C(MITK_PP_BOOL(p##(83, s)), s, p, o, m) # define MITK_PP_FOR_83(s, p, o, m) MITK_PP_FOR_83_C(MITK_PP_BOOL(p##(84, s)), s, p, o, m) # define MITK_PP_FOR_84(s, p, o, m) MITK_PP_FOR_84_C(MITK_PP_BOOL(p##(85, s)), s, p, o, m) # define MITK_PP_FOR_85(s, p, o, m) MITK_PP_FOR_85_C(MITK_PP_BOOL(p##(86, s)), s, p, o, m) # define MITK_PP_FOR_86(s, p, o, m) MITK_PP_FOR_86_C(MITK_PP_BOOL(p##(87, s)), s, p, o, m) # define MITK_PP_FOR_87(s, p, o, m) MITK_PP_FOR_87_C(MITK_PP_BOOL(p##(88, s)), s, p, o, m) # define MITK_PP_FOR_88(s, p, o, m) MITK_PP_FOR_88_C(MITK_PP_BOOL(p##(89, s)), s, p, o, m) # define MITK_PP_FOR_89(s, p, o, m) MITK_PP_FOR_89_C(MITK_PP_BOOL(p##(90, s)), s, p, o, m) # define MITK_PP_FOR_90(s, p, o, m) MITK_PP_FOR_90_C(MITK_PP_BOOL(p##(91, s)), s, p, o, m) # define MITK_PP_FOR_91(s, p, o, m) MITK_PP_FOR_91_C(MITK_PP_BOOL(p##(92, s)), s, p, o, m) # define MITK_PP_FOR_92(s, p, o, m) MITK_PP_FOR_92_C(MITK_PP_BOOL(p##(93, s)), s, p, o, m) # define MITK_PP_FOR_93(s, p, o, m) MITK_PP_FOR_93_C(MITK_PP_BOOL(p##(94, s)), s, p, o, m) # define MITK_PP_FOR_94(s, p, o, m) MITK_PP_FOR_94_C(MITK_PP_BOOL(p##(95, s)), s, p, o, m) # define MITK_PP_FOR_95(s, p, o, m) MITK_PP_FOR_95_C(MITK_PP_BOOL(p##(96, s)), s, p, o, m) # define MITK_PP_FOR_96(s, p, o, m) MITK_PP_FOR_96_C(MITK_PP_BOOL(p##(97, s)), s, p, o, m) # define MITK_PP_FOR_97(s, p, o, m) MITK_PP_FOR_97_C(MITK_PP_BOOL(p##(98, s)), s, p, o, m) # define MITK_PP_FOR_98(s, p, o, m) MITK_PP_FOR_98_C(MITK_PP_BOOL(p##(99, s)), s, p, o, m) # define MITK_PP_FOR_99(s, p, o, m) MITK_PP_FOR_99_C(MITK_PP_BOOL(p##(100, s)), s, p, o, m) # define MITK_PP_FOR_100(s, p, o, m) MITK_PP_FOR_100_C(MITK_PP_BOOL(p##(101, s)), s, p, o, m) # define MITK_PP_FOR_101(s, p, o, m) MITK_PP_FOR_101_C(MITK_PP_BOOL(p##(102, s)), s, p, o, m) # define MITK_PP_FOR_102(s, p, o, m) MITK_PP_FOR_102_C(MITK_PP_BOOL(p##(103, s)), s, p, o, m) # define MITK_PP_FOR_103(s, p, o, m) MITK_PP_FOR_103_C(MITK_PP_BOOL(p##(104, s)), s, p, o, m) # define MITK_PP_FOR_104(s, p, o, m) MITK_PP_FOR_104_C(MITK_PP_BOOL(p##(105, s)), s, p, o, m) # define MITK_PP_FOR_105(s, p, o, m) MITK_PP_FOR_105_C(MITK_PP_BOOL(p##(106, s)), s, p, o, m) # define MITK_PP_FOR_106(s, p, o, m) MITK_PP_FOR_106_C(MITK_PP_BOOL(p##(107, s)), s, p, o, m) # define MITK_PP_FOR_107(s, p, o, m) MITK_PP_FOR_107_C(MITK_PP_BOOL(p##(108, s)), s, p, o, m) # define MITK_PP_FOR_108(s, p, o, m) MITK_PP_FOR_108_C(MITK_PP_BOOL(p##(109, s)), s, p, o, m) # define MITK_PP_FOR_109(s, p, o, m) MITK_PP_FOR_109_C(MITK_PP_BOOL(p##(110, s)), s, p, o, m) # define MITK_PP_FOR_110(s, p, o, m) MITK_PP_FOR_110_C(MITK_PP_BOOL(p##(111, s)), s, p, o, m) # define MITK_PP_FOR_111(s, p, o, m) MITK_PP_FOR_111_C(MITK_PP_BOOL(p##(112, s)), s, p, o, m) # define MITK_PP_FOR_112(s, p, o, m) MITK_PP_FOR_112_C(MITK_PP_BOOL(p##(113, s)), s, p, o, m) # define MITK_PP_FOR_113(s, p, o, m) MITK_PP_FOR_113_C(MITK_PP_BOOL(p##(114, s)), s, p, o, m) # define MITK_PP_FOR_114(s, p, o, m) MITK_PP_FOR_114_C(MITK_PP_BOOL(p##(115, s)), s, p, o, m) # define MITK_PP_FOR_115(s, p, o, m) MITK_PP_FOR_115_C(MITK_PP_BOOL(p##(116, s)), s, p, o, m) # define MITK_PP_FOR_116(s, p, o, m) MITK_PP_FOR_116_C(MITK_PP_BOOL(p##(117, s)), s, p, o, m) # define MITK_PP_FOR_117(s, p, o, m) MITK_PP_FOR_117_C(MITK_PP_BOOL(p##(118, s)), s, p, o, m) # define MITK_PP_FOR_118(s, p, o, m) MITK_PP_FOR_118_C(MITK_PP_BOOL(p##(119, s)), s, p, o, m) # define MITK_PP_FOR_119(s, p, o, m) MITK_PP_FOR_119_C(MITK_PP_BOOL(p##(120, s)), s, p, o, m) # define MITK_PP_FOR_120(s, p, o, m) MITK_PP_FOR_120_C(MITK_PP_BOOL(p##(121, s)), s, p, o, m) # define MITK_PP_FOR_121(s, p, o, m) MITK_PP_FOR_121_C(MITK_PP_BOOL(p##(122, s)), s, p, o, m) # define MITK_PP_FOR_122(s, p, o, m) MITK_PP_FOR_122_C(MITK_PP_BOOL(p##(123, s)), s, p, o, m) # define MITK_PP_FOR_123(s, p, o, m) MITK_PP_FOR_123_C(MITK_PP_BOOL(p##(124, s)), s, p, o, m) # define MITK_PP_FOR_124(s, p, o, m) MITK_PP_FOR_124_C(MITK_PP_BOOL(p##(125, s)), s, p, o, m) # define MITK_PP_FOR_125(s, p, o, m) MITK_PP_FOR_125_C(MITK_PP_BOOL(p##(126, s)), s, p, o, m) # define MITK_PP_FOR_126(s, p, o, m) MITK_PP_FOR_126_C(MITK_PP_BOOL(p##(127, s)), s, p, o, m) # define MITK_PP_FOR_127(s, p, o, m) MITK_PP_FOR_127_C(MITK_PP_BOOL(p##(128, s)), s, p, o, m) # define MITK_PP_FOR_128(s, p, o, m) MITK_PP_FOR_128_C(MITK_PP_BOOL(p##(129, s)), s, p, o, m) # define MITK_PP_FOR_129(s, p, o, m) MITK_PP_FOR_129_C(MITK_PP_BOOL(p##(130, s)), s, p, o, m) # define MITK_PP_FOR_130(s, p, o, m) MITK_PP_FOR_130_C(MITK_PP_BOOL(p##(131, s)), s, p, o, m) # define MITK_PP_FOR_131(s, p, o, m) MITK_PP_FOR_131_C(MITK_PP_BOOL(p##(132, s)), s, p, o, m) # define MITK_PP_FOR_132(s, p, o, m) MITK_PP_FOR_132_C(MITK_PP_BOOL(p##(133, s)), s, p, o, m) # define MITK_PP_FOR_133(s, p, o, m) MITK_PP_FOR_133_C(MITK_PP_BOOL(p##(134, s)), s, p, o, m) # define MITK_PP_FOR_134(s, p, o, m) MITK_PP_FOR_134_C(MITK_PP_BOOL(p##(135, s)), s, p, o, m) # define MITK_PP_FOR_135(s, p, o, m) MITK_PP_FOR_135_C(MITK_PP_BOOL(p##(136, s)), s, p, o, m) # define MITK_PP_FOR_136(s, p, o, m) MITK_PP_FOR_136_C(MITK_PP_BOOL(p##(137, s)), s, p, o, m) # define MITK_PP_FOR_137(s, p, o, m) MITK_PP_FOR_137_C(MITK_PP_BOOL(p##(138, s)), s, p, o, m) # define MITK_PP_FOR_138(s, p, o, m) MITK_PP_FOR_138_C(MITK_PP_BOOL(p##(139, s)), s, p, o, m) # define MITK_PP_FOR_139(s, p, o, m) MITK_PP_FOR_139_C(MITK_PP_BOOL(p##(140, s)), s, p, o, m) # define MITK_PP_FOR_140(s, p, o, m) MITK_PP_FOR_140_C(MITK_PP_BOOL(p##(141, s)), s, p, o, m) # define MITK_PP_FOR_141(s, p, o, m) MITK_PP_FOR_141_C(MITK_PP_BOOL(p##(142, s)), s, p, o, m) # define MITK_PP_FOR_142(s, p, o, m) MITK_PP_FOR_142_C(MITK_PP_BOOL(p##(143, s)), s, p, o, m) # define MITK_PP_FOR_143(s, p, o, m) MITK_PP_FOR_143_C(MITK_PP_BOOL(p##(144, s)), s, p, o, m) # define MITK_PP_FOR_144(s, p, o, m) MITK_PP_FOR_144_C(MITK_PP_BOOL(p##(145, s)), s, p, o, m) # define MITK_PP_FOR_145(s, p, o, m) MITK_PP_FOR_145_C(MITK_PP_BOOL(p##(146, s)), s, p, o, m) # define MITK_PP_FOR_146(s, p, o, m) MITK_PP_FOR_146_C(MITK_PP_BOOL(p##(147, s)), s, p, o, m) # define MITK_PP_FOR_147(s, p, o, m) MITK_PP_FOR_147_C(MITK_PP_BOOL(p##(148, s)), s, p, o, m) # define MITK_PP_FOR_148(s, p, o, m) MITK_PP_FOR_148_C(MITK_PP_BOOL(p##(149, s)), s, p, o, m) # define MITK_PP_FOR_149(s, p, o, m) MITK_PP_FOR_149_C(MITK_PP_BOOL(p##(150, s)), s, p, o, m) # define MITK_PP_FOR_150(s, p, o, m) MITK_PP_FOR_150_C(MITK_PP_BOOL(p##(151, s)), s, p, o, m) # define MITK_PP_FOR_151(s, p, o, m) MITK_PP_FOR_151_C(MITK_PP_BOOL(p##(152, s)), s, p, o, m) # define MITK_PP_FOR_152(s, p, o, m) MITK_PP_FOR_152_C(MITK_PP_BOOL(p##(153, s)), s, p, o, m) # define MITK_PP_FOR_153(s, p, o, m) MITK_PP_FOR_153_C(MITK_PP_BOOL(p##(154, s)), s, p, o, m) # define MITK_PP_FOR_154(s, p, o, m) MITK_PP_FOR_154_C(MITK_PP_BOOL(p##(155, s)), s, p, o, m) # define MITK_PP_FOR_155(s, p, o, m) MITK_PP_FOR_155_C(MITK_PP_BOOL(p##(156, s)), s, p, o, m) # define MITK_PP_FOR_156(s, p, o, m) MITK_PP_FOR_156_C(MITK_PP_BOOL(p##(157, s)), s, p, o, m) # define MITK_PP_FOR_157(s, p, o, m) MITK_PP_FOR_157_C(MITK_PP_BOOL(p##(158, s)), s, p, o, m) # define MITK_PP_FOR_158(s, p, o, m) MITK_PP_FOR_158_C(MITK_PP_BOOL(p##(159, s)), s, p, o, m) # define MITK_PP_FOR_159(s, p, o, m) MITK_PP_FOR_159_C(MITK_PP_BOOL(p##(160, s)), s, p, o, m) # define MITK_PP_FOR_160(s, p, o, m) MITK_PP_FOR_160_C(MITK_PP_BOOL(p##(161, s)), s, p, o, m) # define MITK_PP_FOR_161(s, p, o, m) MITK_PP_FOR_161_C(MITK_PP_BOOL(p##(162, s)), s, p, o, m) # define MITK_PP_FOR_162(s, p, o, m) MITK_PP_FOR_162_C(MITK_PP_BOOL(p##(163, s)), s, p, o, m) # define MITK_PP_FOR_163(s, p, o, m) MITK_PP_FOR_163_C(MITK_PP_BOOL(p##(164, s)), s, p, o, m) # define MITK_PP_FOR_164(s, p, o, m) MITK_PP_FOR_164_C(MITK_PP_BOOL(p##(165, s)), s, p, o, m) # define MITK_PP_FOR_165(s, p, o, m) MITK_PP_FOR_165_C(MITK_PP_BOOL(p##(166, s)), s, p, o, m) # define MITK_PP_FOR_166(s, p, o, m) MITK_PP_FOR_166_C(MITK_PP_BOOL(p##(167, s)), s, p, o, m) # define MITK_PP_FOR_167(s, p, o, m) MITK_PP_FOR_167_C(MITK_PP_BOOL(p##(168, s)), s, p, o, m) # define MITK_PP_FOR_168(s, p, o, m) MITK_PP_FOR_168_C(MITK_PP_BOOL(p##(169, s)), s, p, o, m) # define MITK_PP_FOR_169(s, p, o, m) MITK_PP_FOR_169_C(MITK_PP_BOOL(p##(170, s)), s, p, o, m) # define MITK_PP_FOR_170(s, p, o, m) MITK_PP_FOR_170_C(MITK_PP_BOOL(p##(171, s)), s, p, o, m) # define MITK_PP_FOR_171(s, p, o, m) MITK_PP_FOR_171_C(MITK_PP_BOOL(p##(172, s)), s, p, o, m) # define MITK_PP_FOR_172(s, p, o, m) MITK_PP_FOR_172_C(MITK_PP_BOOL(p##(173, s)), s, p, o, m) # define MITK_PP_FOR_173(s, p, o, m) MITK_PP_FOR_173_C(MITK_PP_BOOL(p##(174, s)), s, p, o, m) # define MITK_PP_FOR_174(s, p, o, m) MITK_PP_FOR_174_C(MITK_PP_BOOL(p##(175, s)), s, p, o, m) # define MITK_PP_FOR_175(s, p, o, m) MITK_PP_FOR_175_C(MITK_PP_BOOL(p##(176, s)), s, p, o, m) # define MITK_PP_FOR_176(s, p, o, m) MITK_PP_FOR_176_C(MITK_PP_BOOL(p##(177, s)), s, p, o, m) # define MITK_PP_FOR_177(s, p, o, m) MITK_PP_FOR_177_C(MITK_PP_BOOL(p##(178, s)), s, p, o, m) # define MITK_PP_FOR_178(s, p, o, m) MITK_PP_FOR_178_C(MITK_PP_BOOL(p##(179, s)), s, p, o, m) # define MITK_PP_FOR_179(s, p, o, m) MITK_PP_FOR_179_C(MITK_PP_BOOL(p##(180, s)), s, p, o, m) # define MITK_PP_FOR_180(s, p, o, m) MITK_PP_FOR_180_C(MITK_PP_BOOL(p##(181, s)), s, p, o, m) # define MITK_PP_FOR_181(s, p, o, m) MITK_PP_FOR_181_C(MITK_PP_BOOL(p##(182, s)), s, p, o, m) # define MITK_PP_FOR_182(s, p, o, m) MITK_PP_FOR_182_C(MITK_PP_BOOL(p##(183, s)), s, p, o, m) # define MITK_PP_FOR_183(s, p, o, m) MITK_PP_FOR_183_C(MITK_PP_BOOL(p##(184, s)), s, p, o, m) # define MITK_PP_FOR_184(s, p, o, m) MITK_PP_FOR_184_C(MITK_PP_BOOL(p##(185, s)), s, p, o, m) # define MITK_PP_FOR_185(s, p, o, m) MITK_PP_FOR_185_C(MITK_PP_BOOL(p##(186, s)), s, p, o, m) # define MITK_PP_FOR_186(s, p, o, m) MITK_PP_FOR_186_C(MITK_PP_BOOL(p##(187, s)), s, p, o, m) # define MITK_PP_FOR_187(s, p, o, m) MITK_PP_FOR_187_C(MITK_PP_BOOL(p##(188, s)), s, p, o, m) # define MITK_PP_FOR_188(s, p, o, m) MITK_PP_FOR_188_C(MITK_PP_BOOL(p##(189, s)), s, p, o, m) # define MITK_PP_FOR_189(s, p, o, m) MITK_PP_FOR_189_C(MITK_PP_BOOL(p##(190, s)), s, p, o, m) # define MITK_PP_FOR_190(s, p, o, m) MITK_PP_FOR_190_C(MITK_PP_BOOL(p##(191, s)), s, p, o, m) # define MITK_PP_FOR_191(s, p, o, m) MITK_PP_FOR_191_C(MITK_PP_BOOL(p##(192, s)), s, p, o, m) # define MITK_PP_FOR_192(s, p, o, m) MITK_PP_FOR_192_C(MITK_PP_BOOL(p##(193, s)), s, p, o, m) # define MITK_PP_FOR_193(s, p, o, m) MITK_PP_FOR_193_C(MITK_PP_BOOL(p##(194, s)), s, p, o, m) # define MITK_PP_FOR_194(s, p, o, m) MITK_PP_FOR_194_C(MITK_PP_BOOL(p##(195, s)), s, p, o, m) # define MITK_PP_FOR_195(s, p, o, m) MITK_PP_FOR_195_C(MITK_PP_BOOL(p##(196, s)), s, p, o, m) # define MITK_PP_FOR_196(s, p, o, m) MITK_PP_FOR_196_C(MITK_PP_BOOL(p##(197, s)), s, p, o, m) # define MITK_PP_FOR_197(s, p, o, m) MITK_PP_FOR_197_C(MITK_PP_BOOL(p##(198, s)), s, p, o, m) # define MITK_PP_FOR_198(s, p, o, m) MITK_PP_FOR_198_C(MITK_PP_BOOL(p##(199, s)), s, p, o, m) # define MITK_PP_FOR_199(s, p, o, m) MITK_PP_FOR_199_C(MITK_PP_BOOL(p##(200, s)), s, p, o, m) # define MITK_PP_FOR_200(s, p, o, m) MITK_PP_FOR_200_C(MITK_PP_BOOL(p##(201, s)), s, p, o, m) # define MITK_PP_FOR_201(s, p, o, m) MITK_PP_FOR_201_C(MITK_PP_BOOL(p##(202, s)), s, p, o, m) # define MITK_PP_FOR_202(s, p, o, m) MITK_PP_FOR_202_C(MITK_PP_BOOL(p##(203, s)), s, p, o, m) # define MITK_PP_FOR_203(s, p, o, m) MITK_PP_FOR_203_C(MITK_PP_BOOL(p##(204, s)), s, p, o, m) # define MITK_PP_FOR_204(s, p, o, m) MITK_PP_FOR_204_C(MITK_PP_BOOL(p##(205, s)), s, p, o, m) # define MITK_PP_FOR_205(s, p, o, m) MITK_PP_FOR_205_C(MITK_PP_BOOL(p##(206, s)), s, p, o, m) # define MITK_PP_FOR_206(s, p, o, m) MITK_PP_FOR_206_C(MITK_PP_BOOL(p##(207, s)), s, p, o, m) # define MITK_PP_FOR_207(s, p, o, m) MITK_PP_FOR_207_C(MITK_PP_BOOL(p##(208, s)), s, p, o, m) # define MITK_PP_FOR_208(s, p, o, m) MITK_PP_FOR_208_C(MITK_PP_BOOL(p##(209, s)), s, p, o, m) # define MITK_PP_FOR_209(s, p, o, m) MITK_PP_FOR_209_C(MITK_PP_BOOL(p##(210, s)), s, p, o, m) # define MITK_PP_FOR_210(s, p, o, m) MITK_PP_FOR_210_C(MITK_PP_BOOL(p##(211, s)), s, p, o, m) # define MITK_PP_FOR_211(s, p, o, m) MITK_PP_FOR_211_C(MITK_PP_BOOL(p##(212, s)), s, p, o, m) # define MITK_PP_FOR_212(s, p, o, m) MITK_PP_FOR_212_C(MITK_PP_BOOL(p##(213, s)), s, p, o, m) # define MITK_PP_FOR_213(s, p, o, m) MITK_PP_FOR_213_C(MITK_PP_BOOL(p##(214, s)), s, p, o, m) # define MITK_PP_FOR_214(s, p, o, m) MITK_PP_FOR_214_C(MITK_PP_BOOL(p##(215, s)), s, p, o, m) # define MITK_PP_FOR_215(s, p, o, m) MITK_PP_FOR_215_C(MITK_PP_BOOL(p##(216, s)), s, p, o, m) # define MITK_PP_FOR_216(s, p, o, m) MITK_PP_FOR_216_C(MITK_PP_BOOL(p##(217, s)), s, p, o, m) # define MITK_PP_FOR_217(s, p, o, m) MITK_PP_FOR_217_C(MITK_PP_BOOL(p##(218, s)), s, p, o, m) # define MITK_PP_FOR_218(s, p, o, m) MITK_PP_FOR_218_C(MITK_PP_BOOL(p##(219, s)), s, p, o, m) # define MITK_PP_FOR_219(s, p, o, m) MITK_PP_FOR_219_C(MITK_PP_BOOL(p##(220, s)), s, p, o, m) # define MITK_PP_FOR_220(s, p, o, m) MITK_PP_FOR_220_C(MITK_PP_BOOL(p##(221, s)), s, p, o, m) # define MITK_PP_FOR_221(s, p, o, m) MITK_PP_FOR_221_C(MITK_PP_BOOL(p##(222, s)), s, p, o, m) # define MITK_PP_FOR_222(s, p, o, m) MITK_PP_FOR_222_C(MITK_PP_BOOL(p##(223, s)), s, p, o, m) # define MITK_PP_FOR_223(s, p, o, m) MITK_PP_FOR_223_C(MITK_PP_BOOL(p##(224, s)), s, p, o, m) # define MITK_PP_FOR_224(s, p, o, m) MITK_PP_FOR_224_C(MITK_PP_BOOL(p##(225, s)), s, p, o, m) # define MITK_PP_FOR_225(s, p, o, m) MITK_PP_FOR_225_C(MITK_PP_BOOL(p##(226, s)), s, p, o, m) # define MITK_PP_FOR_226(s, p, o, m) MITK_PP_FOR_226_C(MITK_PP_BOOL(p##(227, s)), s, p, o, m) # define MITK_PP_FOR_227(s, p, o, m) MITK_PP_FOR_227_C(MITK_PP_BOOL(p##(228, s)), s, p, o, m) # define MITK_PP_FOR_228(s, p, o, m) MITK_PP_FOR_228_C(MITK_PP_BOOL(p##(229, s)), s, p, o, m) # define MITK_PP_FOR_229(s, p, o, m) MITK_PP_FOR_229_C(MITK_PP_BOOL(p##(230, s)), s, p, o, m) # define MITK_PP_FOR_230(s, p, o, m) MITK_PP_FOR_230_C(MITK_PP_BOOL(p##(231, s)), s, p, o, m) # define MITK_PP_FOR_231(s, p, o, m) MITK_PP_FOR_231_C(MITK_PP_BOOL(p##(232, s)), s, p, o, m) # define MITK_PP_FOR_232(s, p, o, m) MITK_PP_FOR_232_C(MITK_PP_BOOL(p##(233, s)), s, p, o, m) # define MITK_PP_FOR_233(s, p, o, m) MITK_PP_FOR_233_C(MITK_PP_BOOL(p##(234, s)), s, p, o, m) # define MITK_PP_FOR_234(s, p, o, m) MITK_PP_FOR_234_C(MITK_PP_BOOL(p##(235, s)), s, p, o, m) # define MITK_PP_FOR_235(s, p, o, m) MITK_PP_FOR_235_C(MITK_PP_BOOL(p##(236, s)), s, p, o, m) # define MITK_PP_FOR_236(s, p, o, m) MITK_PP_FOR_236_C(MITK_PP_BOOL(p##(237, s)), s, p, o, m) # define MITK_PP_FOR_237(s, p, o, m) MITK_PP_FOR_237_C(MITK_PP_BOOL(p##(238, s)), s, p, o, m) # define MITK_PP_FOR_238(s, p, o, m) MITK_PP_FOR_238_C(MITK_PP_BOOL(p##(239, s)), s, p, o, m) # define MITK_PP_FOR_239(s, p, o, m) MITK_PP_FOR_239_C(MITK_PP_BOOL(p##(240, s)), s, p, o, m) # define MITK_PP_FOR_240(s, p, o, m) MITK_PP_FOR_240_C(MITK_PP_BOOL(p##(241, s)), s, p, o, m) # define MITK_PP_FOR_241(s, p, o, m) MITK_PP_FOR_241_C(MITK_PP_BOOL(p##(242, s)), s, p, o, m) # define MITK_PP_FOR_242(s, p, o, m) MITK_PP_FOR_242_C(MITK_PP_BOOL(p##(243, s)), s, p, o, m) # define MITK_PP_FOR_243(s, p, o, m) MITK_PP_FOR_243_C(MITK_PP_BOOL(p##(244, s)), s, p, o, m) # define MITK_PP_FOR_244(s, p, o, m) MITK_PP_FOR_244_C(MITK_PP_BOOL(p##(245, s)), s, p, o, m) # define MITK_PP_FOR_245(s, p, o, m) MITK_PP_FOR_245_C(MITK_PP_BOOL(p##(246, s)), s, p, o, m) # define MITK_PP_FOR_246(s, p, o, m) MITK_PP_FOR_246_C(MITK_PP_BOOL(p##(247, s)), s, p, o, m) # define MITK_PP_FOR_247(s, p, o, m) MITK_PP_FOR_247_C(MITK_PP_BOOL(p##(248, s)), s, p, o, m) # define MITK_PP_FOR_248(s, p, o, m) MITK_PP_FOR_248_C(MITK_PP_BOOL(p##(249, s)), s, p, o, m) # define MITK_PP_FOR_249(s, p, o, m) MITK_PP_FOR_249_C(MITK_PP_BOOL(p##(250, s)), s, p, o, m) # define MITK_PP_FOR_250(s, p, o, m) MITK_PP_FOR_250_C(MITK_PP_BOOL(p##(251, s)), s, p, o, m) # define MITK_PP_FOR_251(s, p, o, m) MITK_PP_FOR_251_C(MITK_PP_BOOL(p##(252, s)), s, p, o, m) # define MITK_PP_FOR_252(s, p, o, m) MITK_PP_FOR_252_C(MITK_PP_BOOL(p##(253, s)), s, p, o, m) # define MITK_PP_FOR_253(s, p, o, m) MITK_PP_FOR_253_C(MITK_PP_BOOL(p##(254, s)), s, p, o, m) # define MITK_PP_FOR_254(s, p, o, m) MITK_PP_FOR_254_C(MITK_PP_BOOL(p##(255, s)), s, p, o, m) # define MITK_PP_FOR_255(s, p, o, m) MITK_PP_FOR_255_C(MITK_PP_BOOL(p##(256, s)), s, p, o, m) # define MITK_PP_FOR_256(s, p, o, m) MITK_PP_FOR_256_C(MITK_PP_BOOL(p##(257, s)), s, p, o, m) # # define MITK_PP_FOR_1_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(2, s) MITK_PP_IIF(c, MITK_PP_FOR_2, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(2, s), p, o, m) # define MITK_PP_FOR_2_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(3, s) MITK_PP_IIF(c, MITK_PP_FOR_3, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(3, s), p, o, m) # define MITK_PP_FOR_3_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(4, s) MITK_PP_IIF(c, MITK_PP_FOR_4, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(4, s), p, o, m) # define MITK_PP_FOR_4_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(5, s) MITK_PP_IIF(c, MITK_PP_FOR_5, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(5, s), p, o, m) # define MITK_PP_FOR_5_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(6, s) MITK_PP_IIF(c, MITK_PP_FOR_6, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(6, s), p, o, m) # define MITK_PP_FOR_6_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(7, s) MITK_PP_IIF(c, MITK_PP_FOR_7, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(7, s), p, o, m) # define MITK_PP_FOR_7_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(8, s) MITK_PP_IIF(c, MITK_PP_FOR_8, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(8, s), p, o, m) # define MITK_PP_FOR_8_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(9, s) MITK_PP_IIF(c, MITK_PP_FOR_9, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(9, s), p, o, m) # define MITK_PP_FOR_9_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(10, s) MITK_PP_IIF(c, MITK_PP_FOR_10, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(10, s), p, o, m) # define MITK_PP_FOR_10_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(11, s) MITK_PP_IIF(c, MITK_PP_FOR_11, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(11, s), p, o, m) # define MITK_PP_FOR_11_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(12, s) MITK_PP_IIF(c, MITK_PP_FOR_12, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(12, s), p, o, m) # define MITK_PP_FOR_12_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(13, s) MITK_PP_IIF(c, MITK_PP_FOR_13, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(13, s), p, o, m) # define MITK_PP_FOR_13_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(14, s) MITK_PP_IIF(c, MITK_PP_FOR_14, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(14, s), p, o, m) # define MITK_PP_FOR_14_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(15, s) MITK_PP_IIF(c, MITK_PP_FOR_15, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(15, s), p, o, m) # define MITK_PP_FOR_15_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(16, s) MITK_PP_IIF(c, MITK_PP_FOR_16, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(16, s), p, o, m) # define MITK_PP_FOR_16_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(17, s) MITK_PP_IIF(c, MITK_PP_FOR_17, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(17, s), p, o, m) # define MITK_PP_FOR_17_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(18, s) MITK_PP_IIF(c, MITK_PP_FOR_18, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(18, s), p, o, m) # define MITK_PP_FOR_18_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(19, s) MITK_PP_IIF(c, MITK_PP_FOR_19, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(19, s), p, o, m) # define MITK_PP_FOR_19_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(20, s) MITK_PP_IIF(c, MITK_PP_FOR_20, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(20, s), p, o, m) # define MITK_PP_FOR_20_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(21, s) MITK_PP_IIF(c, MITK_PP_FOR_21, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(21, s), p, o, m) # define MITK_PP_FOR_21_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(22, s) MITK_PP_IIF(c, MITK_PP_FOR_22, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(22, s), p, o, m) # define MITK_PP_FOR_22_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(23, s) MITK_PP_IIF(c, MITK_PP_FOR_23, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(23, s), p, o, m) # define MITK_PP_FOR_23_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(24, s) MITK_PP_IIF(c, MITK_PP_FOR_24, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(24, s), p, o, m) # define MITK_PP_FOR_24_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(25, s) MITK_PP_IIF(c, MITK_PP_FOR_25, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(25, s), p, o, m) # define MITK_PP_FOR_25_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(26, s) MITK_PP_IIF(c, MITK_PP_FOR_26, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(26, s), p, o, m) # define MITK_PP_FOR_26_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(27, s) MITK_PP_IIF(c, MITK_PP_FOR_27, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(27, s), p, o, m) # define MITK_PP_FOR_27_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(28, s) MITK_PP_IIF(c, MITK_PP_FOR_28, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(28, s), p, o, m) # define MITK_PP_FOR_28_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(29, s) MITK_PP_IIF(c, MITK_PP_FOR_29, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(29, s), p, o, m) # define MITK_PP_FOR_29_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(30, s) MITK_PP_IIF(c, MITK_PP_FOR_30, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(30, s), p, o, m) # define MITK_PP_FOR_30_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(31, s) MITK_PP_IIF(c, MITK_PP_FOR_31, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(31, s), p, o, m) # define MITK_PP_FOR_31_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(32, s) MITK_PP_IIF(c, MITK_PP_FOR_32, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(32, s), p, o, m) # define MITK_PP_FOR_32_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(33, s) MITK_PP_IIF(c, MITK_PP_FOR_33, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(33, s), p, o, m) # define MITK_PP_FOR_33_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(34, s) MITK_PP_IIF(c, MITK_PP_FOR_34, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(34, s), p, o, m) # define MITK_PP_FOR_34_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(35, s) MITK_PP_IIF(c, MITK_PP_FOR_35, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(35, s), p, o, m) # define MITK_PP_FOR_35_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(36, s) MITK_PP_IIF(c, MITK_PP_FOR_36, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(36, s), p, o, m) # define MITK_PP_FOR_36_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(37, s) MITK_PP_IIF(c, MITK_PP_FOR_37, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(37, s), p, o, m) # define MITK_PP_FOR_37_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(38, s) MITK_PP_IIF(c, MITK_PP_FOR_38, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(38, s), p, o, m) # define MITK_PP_FOR_38_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(39, s) MITK_PP_IIF(c, MITK_PP_FOR_39, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(39, s), p, o, m) # define MITK_PP_FOR_39_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(40, s) MITK_PP_IIF(c, MITK_PP_FOR_40, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(40, s), p, o, m) # define MITK_PP_FOR_40_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(41, s) MITK_PP_IIF(c, MITK_PP_FOR_41, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(41, s), p, o, m) # define MITK_PP_FOR_41_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(42, s) MITK_PP_IIF(c, MITK_PP_FOR_42, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(42, s), p, o, m) # define MITK_PP_FOR_42_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(43, s) MITK_PP_IIF(c, MITK_PP_FOR_43, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(43, s), p, o, m) # define MITK_PP_FOR_43_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(44, s) MITK_PP_IIF(c, MITK_PP_FOR_44, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(44, s), p, o, m) # define MITK_PP_FOR_44_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(45, s) MITK_PP_IIF(c, MITK_PP_FOR_45, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(45, s), p, o, m) # define MITK_PP_FOR_45_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(46, s) MITK_PP_IIF(c, MITK_PP_FOR_46, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(46, s), p, o, m) # define MITK_PP_FOR_46_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(47, s) MITK_PP_IIF(c, MITK_PP_FOR_47, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(47, s), p, o, m) # define MITK_PP_FOR_47_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(48, s) MITK_PP_IIF(c, MITK_PP_FOR_48, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(48, s), p, o, m) # define MITK_PP_FOR_48_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(49, s) MITK_PP_IIF(c, MITK_PP_FOR_49, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(49, s), p, o, m) # define MITK_PP_FOR_49_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(50, s) MITK_PP_IIF(c, MITK_PP_FOR_50, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(50, s), p, o, m) # define MITK_PP_FOR_50_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(51, s) MITK_PP_IIF(c, MITK_PP_FOR_51, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(51, s), p, o, m) # define MITK_PP_FOR_51_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(52, s) MITK_PP_IIF(c, MITK_PP_FOR_52, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(52, s), p, o, m) # define MITK_PP_FOR_52_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(53, s) MITK_PP_IIF(c, MITK_PP_FOR_53, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(53, s), p, o, m) # define MITK_PP_FOR_53_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(54, s) MITK_PP_IIF(c, MITK_PP_FOR_54, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(54, s), p, o, m) # define MITK_PP_FOR_54_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(55, s) MITK_PP_IIF(c, MITK_PP_FOR_55, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(55, s), p, o, m) # define MITK_PP_FOR_55_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(56, s) MITK_PP_IIF(c, MITK_PP_FOR_56, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(56, s), p, o, m) # define MITK_PP_FOR_56_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(57, s) MITK_PP_IIF(c, MITK_PP_FOR_57, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(57, s), p, o, m) # define MITK_PP_FOR_57_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(58, s) MITK_PP_IIF(c, MITK_PP_FOR_58, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(58, s), p, o, m) # define MITK_PP_FOR_58_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(59, s) MITK_PP_IIF(c, MITK_PP_FOR_59, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(59, s), p, o, m) # define MITK_PP_FOR_59_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(60, s) MITK_PP_IIF(c, MITK_PP_FOR_60, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(60, s), p, o, m) # define MITK_PP_FOR_60_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(61, s) MITK_PP_IIF(c, MITK_PP_FOR_61, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(61, s), p, o, m) # define MITK_PP_FOR_61_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(62, s) MITK_PP_IIF(c, MITK_PP_FOR_62, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(62, s), p, o, m) # define MITK_PP_FOR_62_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(63, s) MITK_PP_IIF(c, MITK_PP_FOR_63, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(63, s), p, o, m) # define MITK_PP_FOR_63_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(64, s) MITK_PP_IIF(c, MITK_PP_FOR_64, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(64, s), p, o, m) # define MITK_PP_FOR_64_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(65, s) MITK_PP_IIF(c, MITK_PP_FOR_65, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(65, s), p, o, m) # define MITK_PP_FOR_65_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(66, s) MITK_PP_IIF(c, MITK_PP_FOR_66, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(66, s), p, o, m) # define MITK_PP_FOR_66_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(67, s) MITK_PP_IIF(c, MITK_PP_FOR_67, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(67, s), p, o, m) # define MITK_PP_FOR_67_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(68, s) MITK_PP_IIF(c, MITK_PP_FOR_68, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(68, s), p, o, m) # define MITK_PP_FOR_68_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(69, s) MITK_PP_IIF(c, MITK_PP_FOR_69, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(69, s), p, o, m) # define MITK_PP_FOR_69_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(70, s) MITK_PP_IIF(c, MITK_PP_FOR_70, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(70, s), p, o, m) # define MITK_PP_FOR_70_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(71, s) MITK_PP_IIF(c, MITK_PP_FOR_71, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(71, s), p, o, m) # define MITK_PP_FOR_71_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(72, s) MITK_PP_IIF(c, MITK_PP_FOR_72, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(72, s), p, o, m) # define MITK_PP_FOR_72_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(73, s) MITK_PP_IIF(c, MITK_PP_FOR_73, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(73, s), p, o, m) # define MITK_PP_FOR_73_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(74, s) MITK_PP_IIF(c, MITK_PP_FOR_74, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(74, s), p, o, m) # define MITK_PP_FOR_74_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(75, s) MITK_PP_IIF(c, MITK_PP_FOR_75, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(75, s), p, o, m) # define MITK_PP_FOR_75_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(76, s) MITK_PP_IIF(c, MITK_PP_FOR_76, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(76, s), p, o, m) # define MITK_PP_FOR_76_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(77, s) MITK_PP_IIF(c, MITK_PP_FOR_77, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(77, s), p, o, m) # define MITK_PP_FOR_77_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(78, s) MITK_PP_IIF(c, MITK_PP_FOR_78, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(78, s), p, o, m) # define MITK_PP_FOR_78_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(79, s) MITK_PP_IIF(c, MITK_PP_FOR_79, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(79, s), p, o, m) # define MITK_PP_FOR_79_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(80, s) MITK_PP_IIF(c, MITK_PP_FOR_80, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(80, s), p, o, m) # define MITK_PP_FOR_80_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(81, s) MITK_PP_IIF(c, MITK_PP_FOR_81, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(81, s), p, o, m) # define MITK_PP_FOR_81_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(82, s) MITK_PP_IIF(c, MITK_PP_FOR_82, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(82, s), p, o, m) # define MITK_PP_FOR_82_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(83, s) MITK_PP_IIF(c, MITK_PP_FOR_83, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(83, s), p, o, m) # define MITK_PP_FOR_83_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(84, s) MITK_PP_IIF(c, MITK_PP_FOR_84, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(84, s), p, o, m) # define MITK_PP_FOR_84_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(85, s) MITK_PP_IIF(c, MITK_PP_FOR_85, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(85, s), p, o, m) # define MITK_PP_FOR_85_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(86, s) MITK_PP_IIF(c, MITK_PP_FOR_86, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(86, s), p, o, m) # define MITK_PP_FOR_86_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(87, s) MITK_PP_IIF(c, MITK_PP_FOR_87, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(87, s), p, o, m) # define MITK_PP_FOR_87_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(88, s) MITK_PP_IIF(c, MITK_PP_FOR_88, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(88, s), p, o, m) # define MITK_PP_FOR_88_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(89, s) MITK_PP_IIF(c, MITK_PP_FOR_89, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(89, s), p, o, m) # define MITK_PP_FOR_89_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(90, s) MITK_PP_IIF(c, MITK_PP_FOR_90, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(90, s), p, o, m) # define MITK_PP_FOR_90_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(91, s) MITK_PP_IIF(c, MITK_PP_FOR_91, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(91, s), p, o, m) # define MITK_PP_FOR_91_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(92, s) MITK_PP_IIF(c, MITK_PP_FOR_92, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(92, s), p, o, m) # define MITK_PP_FOR_92_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(93, s) MITK_PP_IIF(c, MITK_PP_FOR_93, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(93, s), p, o, m) # define MITK_PP_FOR_93_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(94, s) MITK_PP_IIF(c, MITK_PP_FOR_94, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(94, s), p, o, m) # define MITK_PP_FOR_94_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(95, s) MITK_PP_IIF(c, MITK_PP_FOR_95, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(95, s), p, o, m) # define MITK_PP_FOR_95_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(96, s) MITK_PP_IIF(c, MITK_PP_FOR_96, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(96, s), p, o, m) # define MITK_PP_FOR_96_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(97, s) MITK_PP_IIF(c, MITK_PP_FOR_97, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(97, s), p, o, m) # define MITK_PP_FOR_97_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(98, s) MITK_PP_IIF(c, MITK_PP_FOR_98, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(98, s), p, o, m) # define MITK_PP_FOR_98_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(99, s) MITK_PP_IIF(c, MITK_PP_FOR_99, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(99, s), p, o, m) # define MITK_PP_FOR_99_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(100, s) MITK_PP_IIF(c, MITK_PP_FOR_100, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(100, s), p, o, m) # define MITK_PP_FOR_100_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(101, s) MITK_PP_IIF(c, MITK_PP_FOR_101, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(101, s), p, o, m) # define MITK_PP_FOR_101_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(102, s) MITK_PP_IIF(c, MITK_PP_FOR_102, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(102, s), p, o, m) # define MITK_PP_FOR_102_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(103, s) MITK_PP_IIF(c, MITK_PP_FOR_103, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(103, s), p, o, m) # define MITK_PP_FOR_103_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(104, s) MITK_PP_IIF(c, MITK_PP_FOR_104, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(104, s), p, o, m) # define MITK_PP_FOR_104_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(105, s) MITK_PP_IIF(c, MITK_PP_FOR_105, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(105, s), p, o, m) # define MITK_PP_FOR_105_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(106, s) MITK_PP_IIF(c, MITK_PP_FOR_106, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(106, s), p, o, m) # define MITK_PP_FOR_106_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(107, s) MITK_PP_IIF(c, MITK_PP_FOR_107, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(107, s), p, o, m) # define MITK_PP_FOR_107_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(108, s) MITK_PP_IIF(c, MITK_PP_FOR_108, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(108, s), p, o, m) # define MITK_PP_FOR_108_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(109, s) MITK_PP_IIF(c, MITK_PP_FOR_109, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(109, s), p, o, m) # define MITK_PP_FOR_109_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(110, s) MITK_PP_IIF(c, MITK_PP_FOR_110, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(110, s), p, o, m) # define MITK_PP_FOR_110_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(111, s) MITK_PP_IIF(c, MITK_PP_FOR_111, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(111, s), p, o, m) # define MITK_PP_FOR_111_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(112, s) MITK_PP_IIF(c, MITK_PP_FOR_112, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(112, s), p, o, m) # define MITK_PP_FOR_112_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(113, s) MITK_PP_IIF(c, MITK_PP_FOR_113, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(113, s), p, o, m) # define MITK_PP_FOR_113_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(114, s) MITK_PP_IIF(c, MITK_PP_FOR_114, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(114, s), p, o, m) # define MITK_PP_FOR_114_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(115, s) MITK_PP_IIF(c, MITK_PP_FOR_115, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(115, s), p, o, m) # define MITK_PP_FOR_115_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(116, s) MITK_PP_IIF(c, MITK_PP_FOR_116, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(116, s), p, o, m) # define MITK_PP_FOR_116_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(117, s) MITK_PP_IIF(c, MITK_PP_FOR_117, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(117, s), p, o, m) # define MITK_PP_FOR_117_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(118, s) MITK_PP_IIF(c, MITK_PP_FOR_118, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(118, s), p, o, m) # define MITK_PP_FOR_118_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(119, s) MITK_PP_IIF(c, MITK_PP_FOR_119, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(119, s), p, o, m) # define MITK_PP_FOR_119_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(120, s) MITK_PP_IIF(c, MITK_PP_FOR_120, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(120, s), p, o, m) # define MITK_PP_FOR_120_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(121, s) MITK_PP_IIF(c, MITK_PP_FOR_121, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(121, s), p, o, m) # define MITK_PP_FOR_121_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(122, s) MITK_PP_IIF(c, MITK_PP_FOR_122, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(122, s), p, o, m) # define MITK_PP_FOR_122_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(123, s) MITK_PP_IIF(c, MITK_PP_FOR_123, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(123, s), p, o, m) # define MITK_PP_FOR_123_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(124, s) MITK_PP_IIF(c, MITK_PP_FOR_124, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(124, s), p, o, m) # define MITK_PP_FOR_124_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(125, s) MITK_PP_IIF(c, MITK_PP_FOR_125, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(125, s), p, o, m) # define MITK_PP_FOR_125_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(126, s) MITK_PP_IIF(c, MITK_PP_FOR_126, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(126, s), p, o, m) # define MITK_PP_FOR_126_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(127, s) MITK_PP_IIF(c, MITK_PP_FOR_127, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(127, s), p, o, m) # define MITK_PP_FOR_127_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(128, s) MITK_PP_IIF(c, MITK_PP_FOR_128, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(128, s), p, o, m) # define MITK_PP_FOR_128_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(129, s) MITK_PP_IIF(c, MITK_PP_FOR_129, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(129, s), p, o, m) # define MITK_PP_FOR_129_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(130, s) MITK_PP_IIF(c, MITK_PP_FOR_130, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(130, s), p, o, m) # define MITK_PP_FOR_130_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(131, s) MITK_PP_IIF(c, MITK_PP_FOR_131, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(131, s), p, o, m) # define MITK_PP_FOR_131_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(132, s) MITK_PP_IIF(c, MITK_PP_FOR_132, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(132, s), p, o, m) # define MITK_PP_FOR_132_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(133, s) MITK_PP_IIF(c, MITK_PP_FOR_133, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(133, s), p, o, m) # define MITK_PP_FOR_133_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(134, s) MITK_PP_IIF(c, MITK_PP_FOR_134, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(134, s), p, o, m) # define MITK_PP_FOR_134_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(135, s) MITK_PP_IIF(c, MITK_PP_FOR_135, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(135, s), p, o, m) # define MITK_PP_FOR_135_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(136, s) MITK_PP_IIF(c, MITK_PP_FOR_136, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(136, s), p, o, m) # define MITK_PP_FOR_136_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(137, s) MITK_PP_IIF(c, MITK_PP_FOR_137, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(137, s), p, o, m) # define MITK_PP_FOR_137_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(138, s) MITK_PP_IIF(c, MITK_PP_FOR_138, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(138, s), p, o, m) # define MITK_PP_FOR_138_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(139, s) MITK_PP_IIF(c, MITK_PP_FOR_139, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(139, s), p, o, m) # define MITK_PP_FOR_139_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(140, s) MITK_PP_IIF(c, MITK_PP_FOR_140, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(140, s), p, o, m) # define MITK_PP_FOR_140_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(141, s) MITK_PP_IIF(c, MITK_PP_FOR_141, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(141, s), p, o, m) # define MITK_PP_FOR_141_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(142, s) MITK_PP_IIF(c, MITK_PP_FOR_142, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(142, s), p, o, m) # define MITK_PP_FOR_142_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(143, s) MITK_PP_IIF(c, MITK_PP_FOR_143, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(143, s), p, o, m) # define MITK_PP_FOR_143_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(144, s) MITK_PP_IIF(c, MITK_PP_FOR_144, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(144, s), p, o, m) # define MITK_PP_FOR_144_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(145, s) MITK_PP_IIF(c, MITK_PP_FOR_145, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(145, s), p, o, m) # define MITK_PP_FOR_145_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(146, s) MITK_PP_IIF(c, MITK_PP_FOR_146, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(146, s), p, o, m) # define MITK_PP_FOR_146_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(147, s) MITK_PP_IIF(c, MITK_PP_FOR_147, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(147, s), p, o, m) # define MITK_PP_FOR_147_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(148, s) MITK_PP_IIF(c, MITK_PP_FOR_148, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(148, s), p, o, m) # define MITK_PP_FOR_148_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(149, s) MITK_PP_IIF(c, MITK_PP_FOR_149, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(149, s), p, o, m) # define MITK_PP_FOR_149_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(150, s) MITK_PP_IIF(c, MITK_PP_FOR_150, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(150, s), p, o, m) # define MITK_PP_FOR_150_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(151, s) MITK_PP_IIF(c, MITK_PP_FOR_151, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(151, s), p, o, m) # define MITK_PP_FOR_151_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(152, s) MITK_PP_IIF(c, MITK_PP_FOR_152, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(152, s), p, o, m) # define MITK_PP_FOR_152_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(153, s) MITK_PP_IIF(c, MITK_PP_FOR_153, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(153, s), p, o, m) # define MITK_PP_FOR_153_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(154, s) MITK_PP_IIF(c, MITK_PP_FOR_154, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(154, s), p, o, m) # define MITK_PP_FOR_154_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(155, s) MITK_PP_IIF(c, MITK_PP_FOR_155, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(155, s), p, o, m) # define MITK_PP_FOR_155_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(156, s) MITK_PP_IIF(c, MITK_PP_FOR_156, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(156, s), p, o, m) # define MITK_PP_FOR_156_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(157, s) MITK_PP_IIF(c, MITK_PP_FOR_157, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(157, s), p, o, m) # define MITK_PP_FOR_157_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(158, s) MITK_PP_IIF(c, MITK_PP_FOR_158, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(158, s), p, o, m) # define MITK_PP_FOR_158_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(159, s) MITK_PP_IIF(c, MITK_PP_FOR_159, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(159, s), p, o, m) # define MITK_PP_FOR_159_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(160, s) MITK_PP_IIF(c, MITK_PP_FOR_160, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(160, s), p, o, m) # define MITK_PP_FOR_160_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(161, s) MITK_PP_IIF(c, MITK_PP_FOR_161, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(161, s), p, o, m) # define MITK_PP_FOR_161_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(162, s) MITK_PP_IIF(c, MITK_PP_FOR_162, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(162, s), p, o, m) # define MITK_PP_FOR_162_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(163, s) MITK_PP_IIF(c, MITK_PP_FOR_163, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(163, s), p, o, m) # define MITK_PP_FOR_163_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(164, s) MITK_PP_IIF(c, MITK_PP_FOR_164, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(164, s), p, o, m) # define MITK_PP_FOR_164_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(165, s) MITK_PP_IIF(c, MITK_PP_FOR_165, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(165, s), p, o, m) # define MITK_PP_FOR_165_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(166, s) MITK_PP_IIF(c, MITK_PP_FOR_166, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(166, s), p, o, m) # define MITK_PP_FOR_166_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(167, s) MITK_PP_IIF(c, MITK_PP_FOR_167, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(167, s), p, o, m) # define MITK_PP_FOR_167_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(168, s) MITK_PP_IIF(c, MITK_PP_FOR_168, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(168, s), p, o, m) # define MITK_PP_FOR_168_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(169, s) MITK_PP_IIF(c, MITK_PP_FOR_169, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(169, s), p, o, m) # define MITK_PP_FOR_169_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(170, s) MITK_PP_IIF(c, MITK_PP_FOR_170, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(170, s), p, o, m) # define MITK_PP_FOR_170_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(171, s) MITK_PP_IIF(c, MITK_PP_FOR_171, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(171, s), p, o, m) # define MITK_PP_FOR_171_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(172, s) MITK_PP_IIF(c, MITK_PP_FOR_172, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(172, s), p, o, m) # define MITK_PP_FOR_172_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(173, s) MITK_PP_IIF(c, MITK_PP_FOR_173, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(173, s), p, o, m) # define MITK_PP_FOR_173_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(174, s) MITK_PP_IIF(c, MITK_PP_FOR_174, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(174, s), p, o, m) # define MITK_PP_FOR_174_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(175, s) MITK_PP_IIF(c, MITK_PP_FOR_175, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(175, s), p, o, m) # define MITK_PP_FOR_175_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(176, s) MITK_PP_IIF(c, MITK_PP_FOR_176, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(176, s), p, o, m) # define MITK_PP_FOR_176_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(177, s) MITK_PP_IIF(c, MITK_PP_FOR_177, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(177, s), p, o, m) # define MITK_PP_FOR_177_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(178, s) MITK_PP_IIF(c, MITK_PP_FOR_178, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(178, s), p, o, m) # define MITK_PP_FOR_178_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(179, s) MITK_PP_IIF(c, MITK_PP_FOR_179, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(179, s), p, o, m) # define MITK_PP_FOR_179_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(180, s) MITK_PP_IIF(c, MITK_PP_FOR_180, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(180, s), p, o, m) # define MITK_PP_FOR_180_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(181, s) MITK_PP_IIF(c, MITK_PP_FOR_181, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(181, s), p, o, m) # define MITK_PP_FOR_181_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(182, s) MITK_PP_IIF(c, MITK_PP_FOR_182, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(182, s), p, o, m) # define MITK_PP_FOR_182_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(183, s) MITK_PP_IIF(c, MITK_PP_FOR_183, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(183, s), p, o, m) # define MITK_PP_FOR_183_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(184, s) MITK_PP_IIF(c, MITK_PP_FOR_184, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(184, s), p, o, m) # define MITK_PP_FOR_184_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(185, s) MITK_PP_IIF(c, MITK_PP_FOR_185, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(185, s), p, o, m) # define MITK_PP_FOR_185_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(186, s) MITK_PP_IIF(c, MITK_PP_FOR_186, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(186, s), p, o, m) # define MITK_PP_FOR_186_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(187, s) MITK_PP_IIF(c, MITK_PP_FOR_187, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(187, s), p, o, m) # define MITK_PP_FOR_187_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(188, s) MITK_PP_IIF(c, MITK_PP_FOR_188, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(188, s), p, o, m) # define MITK_PP_FOR_188_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(189, s) MITK_PP_IIF(c, MITK_PP_FOR_189, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(189, s), p, o, m) # define MITK_PP_FOR_189_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(190, s) MITK_PP_IIF(c, MITK_PP_FOR_190, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(190, s), p, o, m) # define MITK_PP_FOR_190_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(191, s) MITK_PP_IIF(c, MITK_PP_FOR_191, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(191, s), p, o, m) # define MITK_PP_FOR_191_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(192, s) MITK_PP_IIF(c, MITK_PP_FOR_192, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(192, s), p, o, m) # define MITK_PP_FOR_192_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(193, s) MITK_PP_IIF(c, MITK_PP_FOR_193, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(193, s), p, o, m) # define MITK_PP_FOR_193_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(194, s) MITK_PP_IIF(c, MITK_PP_FOR_194, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(194, s), p, o, m) # define MITK_PP_FOR_194_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(195, s) MITK_PP_IIF(c, MITK_PP_FOR_195, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(195, s), p, o, m) # define MITK_PP_FOR_195_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(196, s) MITK_PP_IIF(c, MITK_PP_FOR_196, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(196, s), p, o, m) # define MITK_PP_FOR_196_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(197, s) MITK_PP_IIF(c, MITK_PP_FOR_197, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(197, s), p, o, m) # define MITK_PP_FOR_197_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(198, s) MITK_PP_IIF(c, MITK_PP_FOR_198, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(198, s), p, o, m) # define MITK_PP_FOR_198_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(199, s) MITK_PP_IIF(c, MITK_PP_FOR_199, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(199, s), p, o, m) # define MITK_PP_FOR_199_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(200, s) MITK_PP_IIF(c, MITK_PP_FOR_200, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(200, s), p, o, m) # define MITK_PP_FOR_200_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(201, s) MITK_PP_IIF(c, MITK_PP_FOR_201, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(201, s), p, o, m) # define MITK_PP_FOR_201_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(202, s) MITK_PP_IIF(c, MITK_PP_FOR_202, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(202, s), p, o, m) # define MITK_PP_FOR_202_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(203, s) MITK_PP_IIF(c, MITK_PP_FOR_203, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(203, s), p, o, m) # define MITK_PP_FOR_203_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(204, s) MITK_PP_IIF(c, MITK_PP_FOR_204, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(204, s), p, o, m) # define MITK_PP_FOR_204_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(205, s) MITK_PP_IIF(c, MITK_PP_FOR_205, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(205, s), p, o, m) # define MITK_PP_FOR_205_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(206, s) MITK_PP_IIF(c, MITK_PP_FOR_206, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(206, s), p, o, m) # define MITK_PP_FOR_206_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(207, s) MITK_PP_IIF(c, MITK_PP_FOR_207, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(207, s), p, o, m) # define MITK_PP_FOR_207_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(208, s) MITK_PP_IIF(c, MITK_PP_FOR_208, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(208, s), p, o, m) # define MITK_PP_FOR_208_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(209, s) MITK_PP_IIF(c, MITK_PP_FOR_209, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(209, s), p, o, m) # define MITK_PP_FOR_209_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(210, s) MITK_PP_IIF(c, MITK_PP_FOR_210, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(210, s), p, o, m) # define MITK_PP_FOR_210_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(211, s) MITK_PP_IIF(c, MITK_PP_FOR_211, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(211, s), p, o, m) # define MITK_PP_FOR_211_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(212, s) MITK_PP_IIF(c, MITK_PP_FOR_212, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(212, s), p, o, m) # define MITK_PP_FOR_212_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(213, s) MITK_PP_IIF(c, MITK_PP_FOR_213, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(213, s), p, o, m) # define MITK_PP_FOR_213_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(214, s) MITK_PP_IIF(c, MITK_PP_FOR_214, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(214, s), p, o, m) # define MITK_PP_FOR_214_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(215, s) MITK_PP_IIF(c, MITK_PP_FOR_215, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(215, s), p, o, m) # define MITK_PP_FOR_215_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(216, s) MITK_PP_IIF(c, MITK_PP_FOR_216, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(216, s), p, o, m) # define MITK_PP_FOR_216_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(217, s) MITK_PP_IIF(c, MITK_PP_FOR_217, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(217, s), p, o, m) # define MITK_PP_FOR_217_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(218, s) MITK_PP_IIF(c, MITK_PP_FOR_218, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(218, s), p, o, m) # define MITK_PP_FOR_218_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(219, s) MITK_PP_IIF(c, MITK_PP_FOR_219, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(219, s), p, o, m) # define MITK_PP_FOR_219_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(220, s) MITK_PP_IIF(c, MITK_PP_FOR_220, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(220, s), p, o, m) # define MITK_PP_FOR_220_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(221, s) MITK_PP_IIF(c, MITK_PP_FOR_221, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(221, s), p, o, m) # define MITK_PP_FOR_221_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(222, s) MITK_PP_IIF(c, MITK_PP_FOR_222, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(222, s), p, o, m) # define MITK_PP_FOR_222_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(223, s) MITK_PP_IIF(c, MITK_PP_FOR_223, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(223, s), p, o, m) # define MITK_PP_FOR_223_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(224, s) MITK_PP_IIF(c, MITK_PP_FOR_224, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(224, s), p, o, m) # define MITK_PP_FOR_224_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(225, s) MITK_PP_IIF(c, MITK_PP_FOR_225, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(225, s), p, o, m) # define MITK_PP_FOR_225_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(226, s) MITK_PP_IIF(c, MITK_PP_FOR_226, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(226, s), p, o, m) # define MITK_PP_FOR_226_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(227, s) MITK_PP_IIF(c, MITK_PP_FOR_227, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(227, s), p, o, m) # define MITK_PP_FOR_227_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(228, s) MITK_PP_IIF(c, MITK_PP_FOR_228, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(228, s), p, o, m) # define MITK_PP_FOR_228_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(229, s) MITK_PP_IIF(c, MITK_PP_FOR_229, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(229, s), p, o, m) # define MITK_PP_FOR_229_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(230, s) MITK_PP_IIF(c, MITK_PP_FOR_230, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(230, s), p, o, m) # define MITK_PP_FOR_230_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(231, s) MITK_PP_IIF(c, MITK_PP_FOR_231, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(231, s), p, o, m) # define MITK_PP_FOR_231_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(232, s) MITK_PP_IIF(c, MITK_PP_FOR_232, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(232, s), p, o, m) # define MITK_PP_FOR_232_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(233, s) MITK_PP_IIF(c, MITK_PP_FOR_233, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(233, s), p, o, m) # define MITK_PP_FOR_233_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(234, s) MITK_PP_IIF(c, MITK_PP_FOR_234, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(234, s), p, o, m) # define MITK_PP_FOR_234_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(235, s) MITK_PP_IIF(c, MITK_PP_FOR_235, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(235, s), p, o, m) # define MITK_PP_FOR_235_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(236, s) MITK_PP_IIF(c, MITK_PP_FOR_236, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(236, s), p, o, m) # define MITK_PP_FOR_236_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(237, s) MITK_PP_IIF(c, MITK_PP_FOR_237, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(237, s), p, o, m) # define MITK_PP_FOR_237_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(238, s) MITK_PP_IIF(c, MITK_PP_FOR_238, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(238, s), p, o, m) # define MITK_PP_FOR_238_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(239, s) MITK_PP_IIF(c, MITK_PP_FOR_239, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(239, s), p, o, m) # define MITK_PP_FOR_239_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(240, s) MITK_PP_IIF(c, MITK_PP_FOR_240, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(240, s), p, o, m) # define MITK_PP_FOR_240_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(241, s) MITK_PP_IIF(c, MITK_PP_FOR_241, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(241, s), p, o, m) # define MITK_PP_FOR_241_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(242, s) MITK_PP_IIF(c, MITK_PP_FOR_242, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(242, s), p, o, m) # define MITK_PP_FOR_242_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(243, s) MITK_PP_IIF(c, MITK_PP_FOR_243, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(243, s), p, o, m) # define MITK_PP_FOR_243_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(244, s) MITK_PP_IIF(c, MITK_PP_FOR_244, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(244, s), p, o, m) # define MITK_PP_FOR_244_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(245, s) MITK_PP_IIF(c, MITK_PP_FOR_245, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(245, s), p, o, m) # define MITK_PP_FOR_245_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(246, s) MITK_PP_IIF(c, MITK_PP_FOR_246, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(246, s), p, o, m) # define MITK_PP_FOR_246_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(247, s) MITK_PP_IIF(c, MITK_PP_FOR_247, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(247, s), p, o, m) # define MITK_PP_FOR_247_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(248, s) MITK_PP_IIF(c, MITK_PP_FOR_248, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(248, s), p, o, m) # define MITK_PP_FOR_248_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(249, s) MITK_PP_IIF(c, MITK_PP_FOR_249, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(249, s), p, o, m) # define MITK_PP_FOR_249_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(250, s) MITK_PP_IIF(c, MITK_PP_FOR_250, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(250, s), p, o, m) # define MITK_PP_FOR_250_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(251, s) MITK_PP_IIF(c, MITK_PP_FOR_251, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(251, s), p, o, m) # define MITK_PP_FOR_251_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(252, s) MITK_PP_IIF(c, MITK_PP_FOR_252, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(252, s), p, o, m) # define MITK_PP_FOR_252_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(253, s) MITK_PP_IIF(c, MITK_PP_FOR_253, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(253, s), p, o, m) # define MITK_PP_FOR_253_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(254, s) MITK_PP_IIF(c, MITK_PP_FOR_254, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(254, s), p, o, m) # define MITK_PP_FOR_254_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(255, s) MITK_PP_IIF(c, MITK_PP_FOR_255, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(255, s), p, o, m) # define MITK_PP_FOR_255_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(256, s) MITK_PP_IIF(c, MITK_PP_FOR_256, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(256, s), p, o, m) # define MITK_PP_FOR_256_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(257, s) MITK_PP_IIF(c, MITK_PP_FOR_257, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(257, s), p, o, m) # # endif diff --git a/Core/Code/Algorithms/mitkPPRepetitionDetailEDGFor.h b/Core/Code/Algorithms/mitkPPRepetitionDetailEDGFor.h index 44a214b635..450a6ad366 100644 --- a/Core/Code/Algorithms/mitkPPRepetitionDetailEDGFor.h +++ b/Core/Code/Algorithms/mitkPPRepetitionDetailEDGFor.h @@ -1,534 +1,549 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_REPETITION_DETAIL_EDG_FOR_HPP # define MITK_PREPROCESSOR_REPETITION_DETAIL_EDG_FOR_HPP # # include "mitkPPControlIf.h" # include "mitkPPTupleEat.h" # # define MITK_PP_FOR_1(s, p, o, m) MITK_PP_FOR_1_I(s, p, o, m) # define MITK_PP_FOR_2(s, p, o, m) MITK_PP_FOR_2_I(s, p, o, m) # define MITK_PP_FOR_3(s, p, o, m) MITK_PP_FOR_3_I(s, p, o, m) # define MITK_PP_FOR_4(s, p, o, m) MITK_PP_FOR_4_I(s, p, o, m) # define MITK_PP_FOR_5(s, p, o, m) MITK_PP_FOR_5_I(s, p, o, m) # define MITK_PP_FOR_6(s, p, o, m) MITK_PP_FOR_6_I(s, p, o, m) # define MITK_PP_FOR_7(s, p, o, m) MITK_PP_FOR_7_I(s, p, o, m) # define MITK_PP_FOR_8(s, p, o, m) MITK_PP_FOR_8_I(s, p, o, m) # define MITK_PP_FOR_9(s, p, o, m) MITK_PP_FOR_9_I(s, p, o, m) # define MITK_PP_FOR_10(s, p, o, m) MITK_PP_FOR_10_I(s, p, o, m) # define MITK_PP_FOR_11(s, p, o, m) MITK_PP_FOR_11_I(s, p, o, m) # define MITK_PP_FOR_12(s, p, o, m) MITK_PP_FOR_12_I(s, p, o, m) # define MITK_PP_FOR_13(s, p, o, m) MITK_PP_FOR_13_I(s, p, o, m) # define MITK_PP_FOR_14(s, p, o, m) MITK_PP_FOR_14_I(s, p, o, m) # define MITK_PP_FOR_15(s, p, o, m) MITK_PP_FOR_15_I(s, p, o, m) # define MITK_PP_FOR_16(s, p, o, m) MITK_PP_FOR_16_I(s, p, o, m) # define MITK_PP_FOR_17(s, p, o, m) MITK_PP_FOR_17_I(s, p, o, m) # define MITK_PP_FOR_18(s, p, o, m) MITK_PP_FOR_18_I(s, p, o, m) # define MITK_PP_FOR_19(s, p, o, m) MITK_PP_FOR_19_I(s, p, o, m) # define MITK_PP_FOR_20(s, p, o, m) MITK_PP_FOR_20_I(s, p, o, m) # define MITK_PP_FOR_21(s, p, o, m) MITK_PP_FOR_21_I(s, p, o, m) # define MITK_PP_FOR_22(s, p, o, m) MITK_PP_FOR_22_I(s, p, o, m) # define MITK_PP_FOR_23(s, p, o, m) MITK_PP_FOR_23_I(s, p, o, m) # define MITK_PP_FOR_24(s, p, o, m) MITK_PP_FOR_24_I(s, p, o, m) # define MITK_PP_FOR_25(s, p, o, m) MITK_PP_FOR_25_I(s, p, o, m) # define MITK_PP_FOR_26(s, p, o, m) MITK_PP_FOR_26_I(s, p, o, m) # define MITK_PP_FOR_27(s, p, o, m) MITK_PP_FOR_27_I(s, p, o, m) # define MITK_PP_FOR_28(s, p, o, m) MITK_PP_FOR_28_I(s, p, o, m) # define MITK_PP_FOR_29(s, p, o, m) MITK_PP_FOR_29_I(s, p, o, m) # define MITK_PP_FOR_30(s, p, o, m) MITK_PP_FOR_30_I(s, p, o, m) # define MITK_PP_FOR_31(s, p, o, m) MITK_PP_FOR_31_I(s, p, o, m) # define MITK_PP_FOR_32(s, p, o, m) MITK_PP_FOR_32_I(s, p, o, m) # define MITK_PP_FOR_33(s, p, o, m) MITK_PP_FOR_33_I(s, p, o, m) # define MITK_PP_FOR_34(s, p, o, m) MITK_PP_FOR_34_I(s, p, o, m) # define MITK_PP_FOR_35(s, p, o, m) MITK_PP_FOR_35_I(s, p, o, m) # define MITK_PP_FOR_36(s, p, o, m) MITK_PP_FOR_36_I(s, p, o, m) # define MITK_PP_FOR_37(s, p, o, m) MITK_PP_FOR_37_I(s, p, o, m) # define MITK_PP_FOR_38(s, p, o, m) MITK_PP_FOR_38_I(s, p, o, m) # define MITK_PP_FOR_39(s, p, o, m) MITK_PP_FOR_39_I(s, p, o, m) # define MITK_PP_FOR_40(s, p, o, m) MITK_PP_FOR_40_I(s, p, o, m) # define MITK_PP_FOR_41(s, p, o, m) MITK_PP_FOR_41_I(s, p, o, m) # define MITK_PP_FOR_42(s, p, o, m) MITK_PP_FOR_42_I(s, p, o, m) # define MITK_PP_FOR_43(s, p, o, m) MITK_PP_FOR_43_I(s, p, o, m) # define MITK_PP_FOR_44(s, p, o, m) MITK_PP_FOR_44_I(s, p, o, m) # define MITK_PP_FOR_45(s, p, o, m) MITK_PP_FOR_45_I(s, p, o, m) # define MITK_PP_FOR_46(s, p, o, m) MITK_PP_FOR_46_I(s, p, o, m) # define MITK_PP_FOR_47(s, p, o, m) MITK_PP_FOR_47_I(s, p, o, m) # define MITK_PP_FOR_48(s, p, o, m) MITK_PP_FOR_48_I(s, p, o, m) # define MITK_PP_FOR_49(s, p, o, m) MITK_PP_FOR_49_I(s, p, o, m) # define MITK_PP_FOR_50(s, p, o, m) MITK_PP_FOR_50_I(s, p, o, m) # define MITK_PP_FOR_51(s, p, o, m) MITK_PP_FOR_51_I(s, p, o, m) # define MITK_PP_FOR_52(s, p, o, m) MITK_PP_FOR_52_I(s, p, o, m) # define MITK_PP_FOR_53(s, p, o, m) MITK_PP_FOR_53_I(s, p, o, m) # define MITK_PP_FOR_54(s, p, o, m) MITK_PP_FOR_54_I(s, p, o, m) # define MITK_PP_FOR_55(s, p, o, m) MITK_PP_FOR_55_I(s, p, o, m) # define MITK_PP_FOR_56(s, p, o, m) MITK_PP_FOR_56_I(s, p, o, m) # define MITK_PP_FOR_57(s, p, o, m) MITK_PP_FOR_57_I(s, p, o, m) # define MITK_PP_FOR_58(s, p, o, m) MITK_PP_FOR_58_I(s, p, o, m) # define MITK_PP_FOR_59(s, p, o, m) MITK_PP_FOR_59_I(s, p, o, m) # define MITK_PP_FOR_60(s, p, o, m) MITK_PP_FOR_60_I(s, p, o, m) # define MITK_PP_FOR_61(s, p, o, m) MITK_PP_FOR_61_I(s, p, o, m) # define MITK_PP_FOR_62(s, p, o, m) MITK_PP_FOR_62_I(s, p, o, m) # define MITK_PP_FOR_63(s, p, o, m) MITK_PP_FOR_63_I(s, p, o, m) # define MITK_PP_FOR_64(s, p, o, m) MITK_PP_FOR_64_I(s, p, o, m) # define MITK_PP_FOR_65(s, p, o, m) MITK_PP_FOR_65_I(s, p, o, m) # define MITK_PP_FOR_66(s, p, o, m) MITK_PP_FOR_66_I(s, p, o, m) # define MITK_PP_FOR_67(s, p, o, m) MITK_PP_FOR_67_I(s, p, o, m) # define MITK_PP_FOR_68(s, p, o, m) MITK_PP_FOR_68_I(s, p, o, m) # define MITK_PP_FOR_69(s, p, o, m) MITK_PP_FOR_69_I(s, p, o, m) # define MITK_PP_FOR_70(s, p, o, m) MITK_PP_FOR_70_I(s, p, o, m) # define MITK_PP_FOR_71(s, p, o, m) MITK_PP_FOR_71_I(s, p, o, m) # define MITK_PP_FOR_72(s, p, o, m) MITK_PP_FOR_72_I(s, p, o, m) # define MITK_PP_FOR_73(s, p, o, m) MITK_PP_FOR_73_I(s, p, o, m) # define MITK_PP_FOR_74(s, p, o, m) MITK_PP_FOR_74_I(s, p, o, m) # define MITK_PP_FOR_75(s, p, o, m) MITK_PP_FOR_75_I(s, p, o, m) # define MITK_PP_FOR_76(s, p, o, m) MITK_PP_FOR_76_I(s, p, o, m) # define MITK_PP_FOR_77(s, p, o, m) MITK_PP_FOR_77_I(s, p, o, m) # define MITK_PP_FOR_78(s, p, o, m) MITK_PP_FOR_78_I(s, p, o, m) # define MITK_PP_FOR_79(s, p, o, m) MITK_PP_FOR_79_I(s, p, o, m) # define MITK_PP_FOR_80(s, p, o, m) MITK_PP_FOR_80_I(s, p, o, m) # define MITK_PP_FOR_81(s, p, o, m) MITK_PP_FOR_81_I(s, p, o, m) # define MITK_PP_FOR_82(s, p, o, m) MITK_PP_FOR_82_I(s, p, o, m) # define MITK_PP_FOR_83(s, p, o, m) MITK_PP_FOR_83_I(s, p, o, m) # define MITK_PP_FOR_84(s, p, o, m) MITK_PP_FOR_84_I(s, p, o, m) # define MITK_PP_FOR_85(s, p, o, m) MITK_PP_FOR_85_I(s, p, o, m) # define MITK_PP_FOR_86(s, p, o, m) MITK_PP_FOR_86_I(s, p, o, m) # define MITK_PP_FOR_87(s, p, o, m) MITK_PP_FOR_87_I(s, p, o, m) # define MITK_PP_FOR_88(s, p, o, m) MITK_PP_FOR_88_I(s, p, o, m) # define MITK_PP_FOR_89(s, p, o, m) MITK_PP_FOR_89_I(s, p, o, m) # define MITK_PP_FOR_90(s, p, o, m) MITK_PP_FOR_90_I(s, p, o, m) # define MITK_PP_FOR_91(s, p, o, m) MITK_PP_FOR_91_I(s, p, o, m) # define MITK_PP_FOR_92(s, p, o, m) MITK_PP_FOR_92_I(s, p, o, m) # define MITK_PP_FOR_93(s, p, o, m) MITK_PP_FOR_93_I(s, p, o, m) # define MITK_PP_FOR_94(s, p, o, m) MITK_PP_FOR_94_I(s, p, o, m) # define MITK_PP_FOR_95(s, p, o, m) MITK_PP_FOR_95_I(s, p, o, m) # define MITK_PP_FOR_96(s, p, o, m) MITK_PP_FOR_96_I(s, p, o, m) # define MITK_PP_FOR_97(s, p, o, m) MITK_PP_FOR_97_I(s, p, o, m) # define MITK_PP_FOR_98(s, p, o, m) MITK_PP_FOR_98_I(s, p, o, m) # define MITK_PP_FOR_99(s, p, o, m) MITK_PP_FOR_99_I(s, p, o, m) # define MITK_PP_FOR_100(s, p, o, m) MITK_PP_FOR_100_I(s, p, o, m) # define MITK_PP_FOR_101(s, p, o, m) MITK_PP_FOR_101_I(s, p, o, m) # define MITK_PP_FOR_102(s, p, o, m) MITK_PP_FOR_102_I(s, p, o, m) # define MITK_PP_FOR_103(s, p, o, m) MITK_PP_FOR_103_I(s, p, o, m) # define MITK_PP_FOR_104(s, p, o, m) MITK_PP_FOR_104_I(s, p, o, m) # define MITK_PP_FOR_105(s, p, o, m) MITK_PP_FOR_105_I(s, p, o, m) # define MITK_PP_FOR_106(s, p, o, m) MITK_PP_FOR_106_I(s, p, o, m) # define MITK_PP_FOR_107(s, p, o, m) MITK_PP_FOR_107_I(s, p, o, m) # define MITK_PP_FOR_108(s, p, o, m) MITK_PP_FOR_108_I(s, p, o, m) # define MITK_PP_FOR_109(s, p, o, m) MITK_PP_FOR_109_I(s, p, o, m) # define MITK_PP_FOR_110(s, p, o, m) MITK_PP_FOR_110_I(s, p, o, m) # define MITK_PP_FOR_111(s, p, o, m) MITK_PP_FOR_111_I(s, p, o, m) # define MITK_PP_FOR_112(s, p, o, m) MITK_PP_FOR_112_I(s, p, o, m) # define MITK_PP_FOR_113(s, p, o, m) MITK_PP_FOR_113_I(s, p, o, m) # define MITK_PP_FOR_114(s, p, o, m) MITK_PP_FOR_114_I(s, p, o, m) # define MITK_PP_FOR_115(s, p, o, m) MITK_PP_FOR_115_I(s, p, o, m) # define MITK_PP_FOR_116(s, p, o, m) MITK_PP_FOR_116_I(s, p, o, m) # define MITK_PP_FOR_117(s, p, o, m) MITK_PP_FOR_117_I(s, p, o, m) # define MITK_PP_FOR_118(s, p, o, m) MITK_PP_FOR_118_I(s, p, o, m) # define MITK_PP_FOR_119(s, p, o, m) MITK_PP_FOR_119_I(s, p, o, m) # define MITK_PP_FOR_120(s, p, o, m) MITK_PP_FOR_120_I(s, p, o, m) # define MITK_PP_FOR_121(s, p, o, m) MITK_PP_FOR_121_I(s, p, o, m) # define MITK_PP_FOR_122(s, p, o, m) MITK_PP_FOR_122_I(s, p, o, m) # define MITK_PP_FOR_123(s, p, o, m) MITK_PP_FOR_123_I(s, p, o, m) # define MITK_PP_FOR_124(s, p, o, m) MITK_PP_FOR_124_I(s, p, o, m) # define MITK_PP_FOR_125(s, p, o, m) MITK_PP_FOR_125_I(s, p, o, m) # define MITK_PP_FOR_126(s, p, o, m) MITK_PP_FOR_126_I(s, p, o, m) # define MITK_PP_FOR_127(s, p, o, m) MITK_PP_FOR_127_I(s, p, o, m) # define MITK_PP_FOR_128(s, p, o, m) MITK_PP_FOR_128_I(s, p, o, m) # define MITK_PP_FOR_129(s, p, o, m) MITK_PP_FOR_129_I(s, p, o, m) # define MITK_PP_FOR_130(s, p, o, m) MITK_PP_FOR_130_I(s, p, o, m) # define MITK_PP_FOR_131(s, p, o, m) MITK_PP_FOR_131_I(s, p, o, m) # define MITK_PP_FOR_132(s, p, o, m) MITK_PP_FOR_132_I(s, p, o, m) # define MITK_PP_FOR_133(s, p, o, m) MITK_PP_FOR_133_I(s, p, o, m) # define MITK_PP_FOR_134(s, p, o, m) MITK_PP_FOR_134_I(s, p, o, m) # define MITK_PP_FOR_135(s, p, o, m) MITK_PP_FOR_135_I(s, p, o, m) # define MITK_PP_FOR_136(s, p, o, m) MITK_PP_FOR_136_I(s, p, o, m) # define MITK_PP_FOR_137(s, p, o, m) MITK_PP_FOR_137_I(s, p, o, m) # define MITK_PP_FOR_138(s, p, o, m) MITK_PP_FOR_138_I(s, p, o, m) # define MITK_PP_FOR_139(s, p, o, m) MITK_PP_FOR_139_I(s, p, o, m) # define MITK_PP_FOR_140(s, p, o, m) MITK_PP_FOR_140_I(s, p, o, m) # define MITK_PP_FOR_141(s, p, o, m) MITK_PP_FOR_141_I(s, p, o, m) # define MITK_PP_FOR_142(s, p, o, m) MITK_PP_FOR_142_I(s, p, o, m) # define MITK_PP_FOR_143(s, p, o, m) MITK_PP_FOR_143_I(s, p, o, m) # define MITK_PP_FOR_144(s, p, o, m) MITK_PP_FOR_144_I(s, p, o, m) # define MITK_PP_FOR_145(s, p, o, m) MITK_PP_FOR_145_I(s, p, o, m) # define MITK_PP_FOR_146(s, p, o, m) MITK_PP_FOR_146_I(s, p, o, m) # define MITK_PP_FOR_147(s, p, o, m) MITK_PP_FOR_147_I(s, p, o, m) # define MITK_PP_FOR_148(s, p, o, m) MITK_PP_FOR_148_I(s, p, o, m) # define MITK_PP_FOR_149(s, p, o, m) MITK_PP_FOR_149_I(s, p, o, m) # define MITK_PP_FOR_150(s, p, o, m) MITK_PP_FOR_150_I(s, p, o, m) # define MITK_PP_FOR_151(s, p, o, m) MITK_PP_FOR_151_I(s, p, o, m) # define MITK_PP_FOR_152(s, p, o, m) MITK_PP_FOR_152_I(s, p, o, m) # define MITK_PP_FOR_153(s, p, o, m) MITK_PP_FOR_153_I(s, p, o, m) # define MITK_PP_FOR_154(s, p, o, m) MITK_PP_FOR_154_I(s, p, o, m) # define MITK_PP_FOR_155(s, p, o, m) MITK_PP_FOR_155_I(s, p, o, m) # define MITK_PP_FOR_156(s, p, o, m) MITK_PP_FOR_156_I(s, p, o, m) # define MITK_PP_FOR_157(s, p, o, m) MITK_PP_FOR_157_I(s, p, o, m) # define MITK_PP_FOR_158(s, p, o, m) MITK_PP_FOR_158_I(s, p, o, m) # define MITK_PP_FOR_159(s, p, o, m) MITK_PP_FOR_159_I(s, p, o, m) # define MITK_PP_FOR_160(s, p, o, m) MITK_PP_FOR_160_I(s, p, o, m) # define MITK_PP_FOR_161(s, p, o, m) MITK_PP_FOR_161_I(s, p, o, m) # define MITK_PP_FOR_162(s, p, o, m) MITK_PP_FOR_162_I(s, p, o, m) # define MITK_PP_FOR_163(s, p, o, m) MITK_PP_FOR_163_I(s, p, o, m) # define MITK_PP_FOR_164(s, p, o, m) MITK_PP_FOR_164_I(s, p, o, m) # define MITK_PP_FOR_165(s, p, o, m) MITK_PP_FOR_165_I(s, p, o, m) # define MITK_PP_FOR_166(s, p, o, m) MITK_PP_FOR_166_I(s, p, o, m) # define MITK_PP_FOR_167(s, p, o, m) MITK_PP_FOR_167_I(s, p, o, m) # define MITK_PP_FOR_168(s, p, o, m) MITK_PP_FOR_168_I(s, p, o, m) # define MITK_PP_FOR_169(s, p, o, m) MITK_PP_FOR_169_I(s, p, o, m) # define MITK_PP_FOR_170(s, p, o, m) MITK_PP_FOR_170_I(s, p, o, m) # define MITK_PP_FOR_171(s, p, o, m) MITK_PP_FOR_171_I(s, p, o, m) # define MITK_PP_FOR_172(s, p, o, m) MITK_PP_FOR_172_I(s, p, o, m) # define MITK_PP_FOR_173(s, p, o, m) MITK_PP_FOR_173_I(s, p, o, m) # define MITK_PP_FOR_174(s, p, o, m) MITK_PP_FOR_174_I(s, p, o, m) # define MITK_PP_FOR_175(s, p, o, m) MITK_PP_FOR_175_I(s, p, o, m) # define MITK_PP_FOR_176(s, p, o, m) MITK_PP_FOR_176_I(s, p, o, m) # define MITK_PP_FOR_177(s, p, o, m) MITK_PP_FOR_177_I(s, p, o, m) # define MITK_PP_FOR_178(s, p, o, m) MITK_PP_FOR_178_I(s, p, o, m) # define MITK_PP_FOR_179(s, p, o, m) MITK_PP_FOR_179_I(s, p, o, m) # define MITK_PP_FOR_180(s, p, o, m) MITK_PP_FOR_180_I(s, p, o, m) # define MITK_PP_FOR_181(s, p, o, m) MITK_PP_FOR_181_I(s, p, o, m) # define MITK_PP_FOR_182(s, p, o, m) MITK_PP_FOR_182_I(s, p, o, m) # define MITK_PP_FOR_183(s, p, o, m) MITK_PP_FOR_183_I(s, p, o, m) # define MITK_PP_FOR_184(s, p, o, m) MITK_PP_FOR_184_I(s, p, o, m) # define MITK_PP_FOR_185(s, p, o, m) MITK_PP_FOR_185_I(s, p, o, m) # define MITK_PP_FOR_186(s, p, o, m) MITK_PP_FOR_186_I(s, p, o, m) # define MITK_PP_FOR_187(s, p, o, m) MITK_PP_FOR_187_I(s, p, o, m) # define MITK_PP_FOR_188(s, p, o, m) MITK_PP_FOR_188_I(s, p, o, m) # define MITK_PP_FOR_189(s, p, o, m) MITK_PP_FOR_189_I(s, p, o, m) # define MITK_PP_FOR_190(s, p, o, m) MITK_PP_FOR_190_I(s, p, o, m) # define MITK_PP_FOR_191(s, p, o, m) MITK_PP_FOR_191_I(s, p, o, m) # define MITK_PP_FOR_192(s, p, o, m) MITK_PP_FOR_192_I(s, p, o, m) # define MITK_PP_FOR_193(s, p, o, m) MITK_PP_FOR_193_I(s, p, o, m) # define MITK_PP_FOR_194(s, p, o, m) MITK_PP_FOR_194_I(s, p, o, m) # define MITK_PP_FOR_195(s, p, o, m) MITK_PP_FOR_195_I(s, p, o, m) # define MITK_PP_FOR_196(s, p, o, m) MITK_PP_FOR_196_I(s, p, o, m) # define MITK_PP_FOR_197(s, p, o, m) MITK_PP_FOR_197_I(s, p, o, m) # define MITK_PP_FOR_198(s, p, o, m) MITK_PP_FOR_198_I(s, p, o, m) # define MITK_PP_FOR_199(s, p, o, m) MITK_PP_FOR_199_I(s, p, o, m) # define MITK_PP_FOR_200(s, p, o, m) MITK_PP_FOR_200_I(s, p, o, m) # define MITK_PP_FOR_201(s, p, o, m) MITK_PP_FOR_201_I(s, p, o, m) # define MITK_PP_FOR_202(s, p, o, m) MITK_PP_FOR_202_I(s, p, o, m) # define MITK_PP_FOR_203(s, p, o, m) MITK_PP_FOR_203_I(s, p, o, m) # define MITK_PP_FOR_204(s, p, o, m) MITK_PP_FOR_204_I(s, p, o, m) # define MITK_PP_FOR_205(s, p, o, m) MITK_PP_FOR_205_I(s, p, o, m) # define MITK_PP_FOR_206(s, p, o, m) MITK_PP_FOR_206_I(s, p, o, m) # define MITK_PP_FOR_207(s, p, o, m) MITK_PP_FOR_207_I(s, p, o, m) # define MITK_PP_FOR_208(s, p, o, m) MITK_PP_FOR_208_I(s, p, o, m) # define MITK_PP_FOR_209(s, p, o, m) MITK_PP_FOR_209_I(s, p, o, m) # define MITK_PP_FOR_210(s, p, o, m) MITK_PP_FOR_210_I(s, p, o, m) # define MITK_PP_FOR_211(s, p, o, m) MITK_PP_FOR_211_I(s, p, o, m) # define MITK_PP_FOR_212(s, p, o, m) MITK_PP_FOR_212_I(s, p, o, m) # define MITK_PP_FOR_213(s, p, o, m) MITK_PP_FOR_213_I(s, p, o, m) # define MITK_PP_FOR_214(s, p, o, m) MITK_PP_FOR_214_I(s, p, o, m) # define MITK_PP_FOR_215(s, p, o, m) MITK_PP_FOR_215_I(s, p, o, m) # define MITK_PP_FOR_216(s, p, o, m) MITK_PP_FOR_216_I(s, p, o, m) # define MITK_PP_FOR_217(s, p, o, m) MITK_PP_FOR_217_I(s, p, o, m) # define MITK_PP_FOR_218(s, p, o, m) MITK_PP_FOR_218_I(s, p, o, m) # define MITK_PP_FOR_219(s, p, o, m) MITK_PP_FOR_219_I(s, p, o, m) # define MITK_PP_FOR_220(s, p, o, m) MITK_PP_FOR_220_I(s, p, o, m) # define MITK_PP_FOR_221(s, p, o, m) MITK_PP_FOR_221_I(s, p, o, m) # define MITK_PP_FOR_222(s, p, o, m) MITK_PP_FOR_222_I(s, p, o, m) # define MITK_PP_FOR_223(s, p, o, m) MITK_PP_FOR_223_I(s, p, o, m) # define MITK_PP_FOR_224(s, p, o, m) MITK_PP_FOR_224_I(s, p, o, m) # define MITK_PP_FOR_225(s, p, o, m) MITK_PP_FOR_225_I(s, p, o, m) # define MITK_PP_FOR_226(s, p, o, m) MITK_PP_FOR_226_I(s, p, o, m) # define MITK_PP_FOR_227(s, p, o, m) MITK_PP_FOR_227_I(s, p, o, m) # define MITK_PP_FOR_228(s, p, o, m) MITK_PP_FOR_228_I(s, p, o, m) # define MITK_PP_FOR_229(s, p, o, m) MITK_PP_FOR_229_I(s, p, o, m) # define MITK_PP_FOR_230(s, p, o, m) MITK_PP_FOR_230_I(s, p, o, m) # define MITK_PP_FOR_231(s, p, o, m) MITK_PP_FOR_231_I(s, p, o, m) # define MITK_PP_FOR_232(s, p, o, m) MITK_PP_FOR_232_I(s, p, o, m) # define MITK_PP_FOR_233(s, p, o, m) MITK_PP_FOR_233_I(s, p, o, m) # define MITK_PP_FOR_234(s, p, o, m) MITK_PP_FOR_234_I(s, p, o, m) # define MITK_PP_FOR_235(s, p, o, m) MITK_PP_FOR_235_I(s, p, o, m) # define MITK_PP_FOR_236(s, p, o, m) MITK_PP_FOR_236_I(s, p, o, m) # define MITK_PP_FOR_237(s, p, o, m) MITK_PP_FOR_237_I(s, p, o, m) # define MITK_PP_FOR_238(s, p, o, m) MITK_PP_FOR_238_I(s, p, o, m) # define MITK_PP_FOR_239(s, p, o, m) MITK_PP_FOR_239_I(s, p, o, m) # define MITK_PP_FOR_240(s, p, o, m) MITK_PP_FOR_240_I(s, p, o, m) # define MITK_PP_FOR_241(s, p, o, m) MITK_PP_FOR_241_I(s, p, o, m) # define MITK_PP_FOR_242(s, p, o, m) MITK_PP_FOR_242_I(s, p, o, m) # define MITK_PP_FOR_243(s, p, o, m) MITK_PP_FOR_243_I(s, p, o, m) # define MITK_PP_FOR_244(s, p, o, m) MITK_PP_FOR_244_I(s, p, o, m) # define MITK_PP_FOR_245(s, p, o, m) MITK_PP_FOR_245_I(s, p, o, m) # define MITK_PP_FOR_246(s, p, o, m) MITK_PP_FOR_246_I(s, p, o, m) # define MITK_PP_FOR_247(s, p, o, m) MITK_PP_FOR_247_I(s, p, o, m) # define MITK_PP_FOR_248(s, p, o, m) MITK_PP_FOR_248_I(s, p, o, m) # define MITK_PP_FOR_249(s, p, o, m) MITK_PP_FOR_249_I(s, p, o, m) # define MITK_PP_FOR_250(s, p, o, m) MITK_PP_FOR_250_I(s, p, o, m) # define MITK_PP_FOR_251(s, p, o, m) MITK_PP_FOR_251_I(s, p, o, m) # define MITK_PP_FOR_252(s, p, o, m) MITK_PP_FOR_252_I(s, p, o, m) # define MITK_PP_FOR_253(s, p, o, m) MITK_PP_FOR_253_I(s, p, o, m) # define MITK_PP_FOR_254(s, p, o, m) MITK_PP_FOR_254_I(s, p, o, m) # define MITK_PP_FOR_255(s, p, o, m) MITK_PP_FOR_255_I(s, p, o, m) # define MITK_PP_FOR_256(s, p, o, m) MITK_PP_FOR_256_I(s, p, o, m) # # define MITK_PP_FOR_1_I(s, p, o, m) MITK_PP_IF(p(2, s), m, MITK_PP_TUPLE_EAT_2)(2, s) MITK_PP_IF(p(2, s), MITK_PP_FOR_2, MITK_PP_TUPLE_EAT_4)(o(2, s), p, o, m) # define MITK_PP_FOR_2_I(s, p, o, m) MITK_PP_IF(p(3, s), m, MITK_PP_TUPLE_EAT_2)(3, s) MITK_PP_IF(p(3, s), MITK_PP_FOR_3, MITK_PP_TUPLE_EAT_4)(o(3, s), p, o, m) # define MITK_PP_FOR_3_I(s, p, o, m) MITK_PP_IF(p(4, s), m, MITK_PP_TUPLE_EAT_2)(4, s) MITK_PP_IF(p(4, s), MITK_PP_FOR_4, MITK_PP_TUPLE_EAT_4)(o(4, s), p, o, m) # define MITK_PP_FOR_4_I(s, p, o, m) MITK_PP_IF(p(5, s), m, MITK_PP_TUPLE_EAT_2)(5, s) MITK_PP_IF(p(5, s), MITK_PP_FOR_5, MITK_PP_TUPLE_EAT_4)(o(5, s), p, o, m) # define MITK_PP_FOR_5_I(s, p, o, m) MITK_PP_IF(p(6, s), m, MITK_PP_TUPLE_EAT_2)(6, s) MITK_PP_IF(p(6, s), MITK_PP_FOR_6, MITK_PP_TUPLE_EAT_4)(o(6, s), p, o, m) # define MITK_PP_FOR_6_I(s, p, o, m) MITK_PP_IF(p(7, s), m, MITK_PP_TUPLE_EAT_2)(7, s) MITK_PP_IF(p(7, s), MITK_PP_FOR_7, MITK_PP_TUPLE_EAT_4)(o(7, s), p, o, m) # define MITK_PP_FOR_7_I(s, p, o, m) MITK_PP_IF(p(8, s), m, MITK_PP_TUPLE_EAT_2)(8, s) MITK_PP_IF(p(8, s), MITK_PP_FOR_8, MITK_PP_TUPLE_EAT_4)(o(8, s), p, o, m) # define MITK_PP_FOR_8_I(s, p, o, m) MITK_PP_IF(p(9, s), m, MITK_PP_TUPLE_EAT_2)(9, s) MITK_PP_IF(p(9, s), MITK_PP_FOR_9, MITK_PP_TUPLE_EAT_4)(o(9, s), p, o, m) # define MITK_PP_FOR_9_I(s, p, o, m) MITK_PP_IF(p(10, s), m, MITK_PP_TUPLE_EAT_2)(10, s) MITK_PP_IF(p(10, s), MITK_PP_FOR_10, MITK_PP_TUPLE_EAT_4)(o(10, s), p, o, m) # define MITK_PP_FOR_10_I(s, p, o, m) MITK_PP_IF(p(11, s), m, MITK_PP_TUPLE_EAT_2)(11, s) MITK_PP_IF(p(11, s), MITK_PP_FOR_11, MITK_PP_TUPLE_EAT_4)(o(11, s), p, o, m) # define MITK_PP_FOR_11_I(s, p, o, m) MITK_PP_IF(p(12, s), m, MITK_PP_TUPLE_EAT_2)(12, s) MITK_PP_IF(p(12, s), MITK_PP_FOR_12, MITK_PP_TUPLE_EAT_4)(o(12, s), p, o, m) # define MITK_PP_FOR_12_I(s, p, o, m) MITK_PP_IF(p(13, s), m, MITK_PP_TUPLE_EAT_2)(13, s) MITK_PP_IF(p(13, s), MITK_PP_FOR_13, MITK_PP_TUPLE_EAT_4)(o(13, s), p, o, m) # define MITK_PP_FOR_13_I(s, p, o, m) MITK_PP_IF(p(14, s), m, MITK_PP_TUPLE_EAT_2)(14, s) MITK_PP_IF(p(14, s), MITK_PP_FOR_14, MITK_PP_TUPLE_EAT_4)(o(14, s), p, o, m) # define MITK_PP_FOR_14_I(s, p, o, m) MITK_PP_IF(p(15, s), m, MITK_PP_TUPLE_EAT_2)(15, s) MITK_PP_IF(p(15, s), MITK_PP_FOR_15, MITK_PP_TUPLE_EAT_4)(o(15, s), p, o, m) # define MITK_PP_FOR_15_I(s, p, o, m) MITK_PP_IF(p(16, s), m, MITK_PP_TUPLE_EAT_2)(16, s) MITK_PP_IF(p(16, s), MITK_PP_FOR_16, MITK_PP_TUPLE_EAT_4)(o(16, s), p, o, m) # define MITK_PP_FOR_16_I(s, p, o, m) MITK_PP_IF(p(17, s), m, MITK_PP_TUPLE_EAT_2)(17, s) MITK_PP_IF(p(17, s), MITK_PP_FOR_17, MITK_PP_TUPLE_EAT_4)(o(17, s), p, o, m) # define MITK_PP_FOR_17_I(s, p, o, m) MITK_PP_IF(p(18, s), m, MITK_PP_TUPLE_EAT_2)(18, s) MITK_PP_IF(p(18, s), MITK_PP_FOR_18, MITK_PP_TUPLE_EAT_4)(o(18, s), p, o, m) # define MITK_PP_FOR_18_I(s, p, o, m) MITK_PP_IF(p(19, s), m, MITK_PP_TUPLE_EAT_2)(19, s) MITK_PP_IF(p(19, s), MITK_PP_FOR_19, MITK_PP_TUPLE_EAT_4)(o(19, s), p, o, m) # define MITK_PP_FOR_19_I(s, p, o, m) MITK_PP_IF(p(20, s), m, MITK_PP_TUPLE_EAT_2)(20, s) MITK_PP_IF(p(20, s), MITK_PP_FOR_20, MITK_PP_TUPLE_EAT_4)(o(20, s), p, o, m) # define MITK_PP_FOR_20_I(s, p, o, m) MITK_PP_IF(p(21, s), m, MITK_PP_TUPLE_EAT_2)(21, s) MITK_PP_IF(p(21, s), MITK_PP_FOR_21, MITK_PP_TUPLE_EAT_4)(o(21, s), p, o, m) # define MITK_PP_FOR_21_I(s, p, o, m) MITK_PP_IF(p(22, s), m, MITK_PP_TUPLE_EAT_2)(22, s) MITK_PP_IF(p(22, s), MITK_PP_FOR_22, MITK_PP_TUPLE_EAT_4)(o(22, s), p, o, m) # define MITK_PP_FOR_22_I(s, p, o, m) MITK_PP_IF(p(23, s), m, MITK_PP_TUPLE_EAT_2)(23, s) MITK_PP_IF(p(23, s), MITK_PP_FOR_23, MITK_PP_TUPLE_EAT_4)(o(23, s), p, o, m) # define MITK_PP_FOR_23_I(s, p, o, m) MITK_PP_IF(p(24, s), m, MITK_PP_TUPLE_EAT_2)(24, s) MITK_PP_IF(p(24, s), MITK_PP_FOR_24, MITK_PP_TUPLE_EAT_4)(o(24, s), p, o, m) # define MITK_PP_FOR_24_I(s, p, o, m) MITK_PP_IF(p(25, s), m, MITK_PP_TUPLE_EAT_2)(25, s) MITK_PP_IF(p(25, s), MITK_PP_FOR_25, MITK_PP_TUPLE_EAT_4)(o(25, s), p, o, m) # define MITK_PP_FOR_25_I(s, p, o, m) MITK_PP_IF(p(26, s), m, MITK_PP_TUPLE_EAT_2)(26, s) MITK_PP_IF(p(26, s), MITK_PP_FOR_26, MITK_PP_TUPLE_EAT_4)(o(26, s), p, o, m) # define MITK_PP_FOR_26_I(s, p, o, m) MITK_PP_IF(p(27, s), m, MITK_PP_TUPLE_EAT_2)(27, s) MITK_PP_IF(p(27, s), MITK_PP_FOR_27, MITK_PP_TUPLE_EAT_4)(o(27, s), p, o, m) # define MITK_PP_FOR_27_I(s, p, o, m) MITK_PP_IF(p(28, s), m, MITK_PP_TUPLE_EAT_2)(28, s) MITK_PP_IF(p(28, s), MITK_PP_FOR_28, MITK_PP_TUPLE_EAT_4)(o(28, s), p, o, m) # define MITK_PP_FOR_28_I(s, p, o, m) MITK_PP_IF(p(29, s), m, MITK_PP_TUPLE_EAT_2)(29, s) MITK_PP_IF(p(29, s), MITK_PP_FOR_29, MITK_PP_TUPLE_EAT_4)(o(29, s), p, o, m) # define MITK_PP_FOR_29_I(s, p, o, m) MITK_PP_IF(p(30, s), m, MITK_PP_TUPLE_EAT_2)(30, s) MITK_PP_IF(p(30, s), MITK_PP_FOR_30, MITK_PP_TUPLE_EAT_4)(o(30, s), p, o, m) # define MITK_PP_FOR_30_I(s, p, o, m) MITK_PP_IF(p(31, s), m, MITK_PP_TUPLE_EAT_2)(31, s) MITK_PP_IF(p(31, s), MITK_PP_FOR_31, MITK_PP_TUPLE_EAT_4)(o(31, s), p, o, m) # define MITK_PP_FOR_31_I(s, p, o, m) MITK_PP_IF(p(32, s), m, MITK_PP_TUPLE_EAT_2)(32, s) MITK_PP_IF(p(32, s), MITK_PP_FOR_32, MITK_PP_TUPLE_EAT_4)(o(32, s), p, o, m) # define MITK_PP_FOR_32_I(s, p, o, m) MITK_PP_IF(p(33, s), m, MITK_PP_TUPLE_EAT_2)(33, s) MITK_PP_IF(p(33, s), MITK_PP_FOR_33, MITK_PP_TUPLE_EAT_4)(o(33, s), p, o, m) # define MITK_PP_FOR_33_I(s, p, o, m) MITK_PP_IF(p(34, s), m, MITK_PP_TUPLE_EAT_2)(34, s) MITK_PP_IF(p(34, s), MITK_PP_FOR_34, MITK_PP_TUPLE_EAT_4)(o(34, s), p, o, m) # define MITK_PP_FOR_34_I(s, p, o, m) MITK_PP_IF(p(35, s), m, MITK_PP_TUPLE_EAT_2)(35, s) MITK_PP_IF(p(35, s), MITK_PP_FOR_35, MITK_PP_TUPLE_EAT_4)(o(35, s), p, o, m) # define MITK_PP_FOR_35_I(s, p, o, m) MITK_PP_IF(p(36, s), m, MITK_PP_TUPLE_EAT_2)(36, s) MITK_PP_IF(p(36, s), MITK_PP_FOR_36, MITK_PP_TUPLE_EAT_4)(o(36, s), p, o, m) # define MITK_PP_FOR_36_I(s, p, o, m) MITK_PP_IF(p(37, s), m, MITK_PP_TUPLE_EAT_2)(37, s) MITK_PP_IF(p(37, s), MITK_PP_FOR_37, MITK_PP_TUPLE_EAT_4)(o(37, s), p, o, m) # define MITK_PP_FOR_37_I(s, p, o, m) MITK_PP_IF(p(38, s), m, MITK_PP_TUPLE_EAT_2)(38, s) MITK_PP_IF(p(38, s), MITK_PP_FOR_38, MITK_PP_TUPLE_EAT_4)(o(38, s), p, o, m) # define MITK_PP_FOR_38_I(s, p, o, m) MITK_PP_IF(p(39, s), m, MITK_PP_TUPLE_EAT_2)(39, s) MITK_PP_IF(p(39, s), MITK_PP_FOR_39, MITK_PP_TUPLE_EAT_4)(o(39, s), p, o, m) # define MITK_PP_FOR_39_I(s, p, o, m) MITK_PP_IF(p(40, s), m, MITK_PP_TUPLE_EAT_2)(40, s) MITK_PP_IF(p(40, s), MITK_PP_FOR_40, MITK_PP_TUPLE_EAT_4)(o(40, s), p, o, m) # define MITK_PP_FOR_40_I(s, p, o, m) MITK_PP_IF(p(41, s), m, MITK_PP_TUPLE_EAT_2)(41, s) MITK_PP_IF(p(41, s), MITK_PP_FOR_41, MITK_PP_TUPLE_EAT_4)(o(41, s), p, o, m) # define MITK_PP_FOR_41_I(s, p, o, m) MITK_PP_IF(p(42, s), m, MITK_PP_TUPLE_EAT_2)(42, s) MITK_PP_IF(p(42, s), MITK_PP_FOR_42, MITK_PP_TUPLE_EAT_4)(o(42, s), p, o, m) # define MITK_PP_FOR_42_I(s, p, o, m) MITK_PP_IF(p(43, s), m, MITK_PP_TUPLE_EAT_2)(43, s) MITK_PP_IF(p(43, s), MITK_PP_FOR_43, MITK_PP_TUPLE_EAT_4)(o(43, s), p, o, m) # define MITK_PP_FOR_43_I(s, p, o, m) MITK_PP_IF(p(44, s), m, MITK_PP_TUPLE_EAT_2)(44, s) MITK_PP_IF(p(44, s), MITK_PP_FOR_44, MITK_PP_TUPLE_EAT_4)(o(44, s), p, o, m) # define MITK_PP_FOR_44_I(s, p, o, m) MITK_PP_IF(p(45, s), m, MITK_PP_TUPLE_EAT_2)(45, s) MITK_PP_IF(p(45, s), MITK_PP_FOR_45, MITK_PP_TUPLE_EAT_4)(o(45, s), p, o, m) # define MITK_PP_FOR_45_I(s, p, o, m) MITK_PP_IF(p(46, s), m, MITK_PP_TUPLE_EAT_2)(46, s) MITK_PP_IF(p(46, s), MITK_PP_FOR_46, MITK_PP_TUPLE_EAT_4)(o(46, s), p, o, m) # define MITK_PP_FOR_46_I(s, p, o, m) MITK_PP_IF(p(47, s), m, MITK_PP_TUPLE_EAT_2)(47, s) MITK_PP_IF(p(47, s), MITK_PP_FOR_47, MITK_PP_TUPLE_EAT_4)(o(47, s), p, o, m) # define MITK_PP_FOR_47_I(s, p, o, m) MITK_PP_IF(p(48, s), m, MITK_PP_TUPLE_EAT_2)(48, s) MITK_PP_IF(p(48, s), MITK_PP_FOR_48, MITK_PP_TUPLE_EAT_4)(o(48, s), p, o, m) # define MITK_PP_FOR_48_I(s, p, o, m) MITK_PP_IF(p(49, s), m, MITK_PP_TUPLE_EAT_2)(49, s) MITK_PP_IF(p(49, s), MITK_PP_FOR_49, MITK_PP_TUPLE_EAT_4)(o(49, s), p, o, m) # define MITK_PP_FOR_49_I(s, p, o, m) MITK_PP_IF(p(50, s), m, MITK_PP_TUPLE_EAT_2)(50, s) MITK_PP_IF(p(50, s), MITK_PP_FOR_50, MITK_PP_TUPLE_EAT_4)(o(50, s), p, o, m) # define MITK_PP_FOR_50_I(s, p, o, m) MITK_PP_IF(p(51, s), m, MITK_PP_TUPLE_EAT_2)(51, s) MITK_PP_IF(p(51, s), MITK_PP_FOR_51, MITK_PP_TUPLE_EAT_4)(o(51, s), p, o, m) # define MITK_PP_FOR_51_I(s, p, o, m) MITK_PP_IF(p(52, s), m, MITK_PP_TUPLE_EAT_2)(52, s) MITK_PP_IF(p(52, s), MITK_PP_FOR_52, MITK_PP_TUPLE_EAT_4)(o(52, s), p, o, m) # define MITK_PP_FOR_52_I(s, p, o, m) MITK_PP_IF(p(53, s), m, MITK_PP_TUPLE_EAT_2)(53, s) MITK_PP_IF(p(53, s), MITK_PP_FOR_53, MITK_PP_TUPLE_EAT_4)(o(53, s), p, o, m) # define MITK_PP_FOR_53_I(s, p, o, m) MITK_PP_IF(p(54, s), m, MITK_PP_TUPLE_EAT_2)(54, s) MITK_PP_IF(p(54, s), MITK_PP_FOR_54, MITK_PP_TUPLE_EAT_4)(o(54, s), p, o, m) # define MITK_PP_FOR_54_I(s, p, o, m) MITK_PP_IF(p(55, s), m, MITK_PP_TUPLE_EAT_2)(55, s) MITK_PP_IF(p(55, s), MITK_PP_FOR_55, MITK_PP_TUPLE_EAT_4)(o(55, s), p, o, m) # define MITK_PP_FOR_55_I(s, p, o, m) MITK_PP_IF(p(56, s), m, MITK_PP_TUPLE_EAT_2)(56, s) MITK_PP_IF(p(56, s), MITK_PP_FOR_56, MITK_PP_TUPLE_EAT_4)(o(56, s), p, o, m) # define MITK_PP_FOR_56_I(s, p, o, m) MITK_PP_IF(p(57, s), m, MITK_PP_TUPLE_EAT_2)(57, s) MITK_PP_IF(p(57, s), MITK_PP_FOR_57, MITK_PP_TUPLE_EAT_4)(o(57, s), p, o, m) # define MITK_PP_FOR_57_I(s, p, o, m) MITK_PP_IF(p(58, s), m, MITK_PP_TUPLE_EAT_2)(58, s) MITK_PP_IF(p(58, s), MITK_PP_FOR_58, MITK_PP_TUPLE_EAT_4)(o(58, s), p, o, m) # define MITK_PP_FOR_58_I(s, p, o, m) MITK_PP_IF(p(59, s), m, MITK_PP_TUPLE_EAT_2)(59, s) MITK_PP_IF(p(59, s), MITK_PP_FOR_59, MITK_PP_TUPLE_EAT_4)(o(59, s), p, o, m) # define MITK_PP_FOR_59_I(s, p, o, m) MITK_PP_IF(p(60, s), m, MITK_PP_TUPLE_EAT_2)(60, s) MITK_PP_IF(p(60, s), MITK_PP_FOR_60, MITK_PP_TUPLE_EAT_4)(o(60, s), p, o, m) # define MITK_PP_FOR_60_I(s, p, o, m) MITK_PP_IF(p(61, s), m, MITK_PP_TUPLE_EAT_2)(61, s) MITK_PP_IF(p(61, s), MITK_PP_FOR_61, MITK_PP_TUPLE_EAT_4)(o(61, s), p, o, m) # define MITK_PP_FOR_61_I(s, p, o, m) MITK_PP_IF(p(62, s), m, MITK_PP_TUPLE_EAT_2)(62, s) MITK_PP_IF(p(62, s), MITK_PP_FOR_62, MITK_PP_TUPLE_EAT_4)(o(62, s), p, o, m) # define MITK_PP_FOR_62_I(s, p, o, m) MITK_PP_IF(p(63, s), m, MITK_PP_TUPLE_EAT_2)(63, s) MITK_PP_IF(p(63, s), MITK_PP_FOR_63, MITK_PP_TUPLE_EAT_4)(o(63, s), p, o, m) # define MITK_PP_FOR_63_I(s, p, o, m) MITK_PP_IF(p(64, s), m, MITK_PP_TUPLE_EAT_2)(64, s) MITK_PP_IF(p(64, s), MITK_PP_FOR_64, MITK_PP_TUPLE_EAT_4)(o(64, s), p, o, m) # define MITK_PP_FOR_64_I(s, p, o, m) MITK_PP_IF(p(65, s), m, MITK_PP_TUPLE_EAT_2)(65, s) MITK_PP_IF(p(65, s), MITK_PP_FOR_65, MITK_PP_TUPLE_EAT_4)(o(65, s), p, o, m) # define MITK_PP_FOR_65_I(s, p, o, m) MITK_PP_IF(p(66, s), m, MITK_PP_TUPLE_EAT_2)(66, s) MITK_PP_IF(p(66, s), MITK_PP_FOR_66, MITK_PP_TUPLE_EAT_4)(o(66, s), p, o, m) # define MITK_PP_FOR_66_I(s, p, o, m) MITK_PP_IF(p(67, s), m, MITK_PP_TUPLE_EAT_2)(67, s) MITK_PP_IF(p(67, s), MITK_PP_FOR_67, MITK_PP_TUPLE_EAT_4)(o(67, s), p, o, m) # define MITK_PP_FOR_67_I(s, p, o, m) MITK_PP_IF(p(68, s), m, MITK_PP_TUPLE_EAT_2)(68, s) MITK_PP_IF(p(68, s), MITK_PP_FOR_68, MITK_PP_TUPLE_EAT_4)(o(68, s), p, o, m) # define MITK_PP_FOR_68_I(s, p, o, m) MITK_PP_IF(p(69, s), m, MITK_PP_TUPLE_EAT_2)(69, s) MITK_PP_IF(p(69, s), MITK_PP_FOR_69, MITK_PP_TUPLE_EAT_4)(o(69, s), p, o, m) # define MITK_PP_FOR_69_I(s, p, o, m) MITK_PP_IF(p(70, s), m, MITK_PP_TUPLE_EAT_2)(70, s) MITK_PP_IF(p(70, s), MITK_PP_FOR_70, MITK_PP_TUPLE_EAT_4)(o(70, s), p, o, m) # define MITK_PP_FOR_70_I(s, p, o, m) MITK_PP_IF(p(71, s), m, MITK_PP_TUPLE_EAT_2)(71, s) MITK_PP_IF(p(71, s), MITK_PP_FOR_71, MITK_PP_TUPLE_EAT_4)(o(71, s), p, o, m) # define MITK_PP_FOR_71_I(s, p, o, m) MITK_PP_IF(p(72, s), m, MITK_PP_TUPLE_EAT_2)(72, s) MITK_PP_IF(p(72, s), MITK_PP_FOR_72, MITK_PP_TUPLE_EAT_4)(o(72, s), p, o, m) # define MITK_PP_FOR_72_I(s, p, o, m) MITK_PP_IF(p(73, s), m, MITK_PP_TUPLE_EAT_2)(73, s) MITK_PP_IF(p(73, s), MITK_PP_FOR_73, MITK_PP_TUPLE_EAT_4)(o(73, s), p, o, m) # define MITK_PP_FOR_73_I(s, p, o, m) MITK_PP_IF(p(74, s), m, MITK_PP_TUPLE_EAT_2)(74, s) MITK_PP_IF(p(74, s), MITK_PP_FOR_74, MITK_PP_TUPLE_EAT_4)(o(74, s), p, o, m) # define MITK_PP_FOR_74_I(s, p, o, m) MITK_PP_IF(p(75, s), m, MITK_PP_TUPLE_EAT_2)(75, s) MITK_PP_IF(p(75, s), MITK_PP_FOR_75, MITK_PP_TUPLE_EAT_4)(o(75, s), p, o, m) # define MITK_PP_FOR_75_I(s, p, o, m) MITK_PP_IF(p(76, s), m, MITK_PP_TUPLE_EAT_2)(76, s) MITK_PP_IF(p(76, s), MITK_PP_FOR_76, MITK_PP_TUPLE_EAT_4)(o(76, s), p, o, m) # define MITK_PP_FOR_76_I(s, p, o, m) MITK_PP_IF(p(77, s), m, MITK_PP_TUPLE_EAT_2)(77, s) MITK_PP_IF(p(77, s), MITK_PP_FOR_77, MITK_PP_TUPLE_EAT_4)(o(77, s), p, o, m) # define MITK_PP_FOR_77_I(s, p, o, m) MITK_PP_IF(p(78, s), m, MITK_PP_TUPLE_EAT_2)(78, s) MITK_PP_IF(p(78, s), MITK_PP_FOR_78, MITK_PP_TUPLE_EAT_4)(o(78, s), p, o, m) # define MITK_PP_FOR_78_I(s, p, o, m) MITK_PP_IF(p(79, s), m, MITK_PP_TUPLE_EAT_2)(79, s) MITK_PP_IF(p(79, s), MITK_PP_FOR_79, MITK_PP_TUPLE_EAT_4)(o(79, s), p, o, m) # define MITK_PP_FOR_79_I(s, p, o, m) MITK_PP_IF(p(80, s), m, MITK_PP_TUPLE_EAT_2)(80, s) MITK_PP_IF(p(80, s), MITK_PP_FOR_80, MITK_PP_TUPLE_EAT_4)(o(80, s), p, o, m) # define MITK_PP_FOR_80_I(s, p, o, m) MITK_PP_IF(p(81, s), m, MITK_PP_TUPLE_EAT_2)(81, s) MITK_PP_IF(p(81, s), MITK_PP_FOR_81, MITK_PP_TUPLE_EAT_4)(o(81, s), p, o, m) # define MITK_PP_FOR_81_I(s, p, o, m) MITK_PP_IF(p(82, s), m, MITK_PP_TUPLE_EAT_2)(82, s) MITK_PP_IF(p(82, s), MITK_PP_FOR_82, MITK_PP_TUPLE_EAT_4)(o(82, s), p, o, m) # define MITK_PP_FOR_82_I(s, p, o, m) MITK_PP_IF(p(83, s), m, MITK_PP_TUPLE_EAT_2)(83, s) MITK_PP_IF(p(83, s), MITK_PP_FOR_83, MITK_PP_TUPLE_EAT_4)(o(83, s), p, o, m) # define MITK_PP_FOR_83_I(s, p, o, m) MITK_PP_IF(p(84, s), m, MITK_PP_TUPLE_EAT_2)(84, s) MITK_PP_IF(p(84, s), MITK_PP_FOR_84, MITK_PP_TUPLE_EAT_4)(o(84, s), p, o, m) # define MITK_PP_FOR_84_I(s, p, o, m) MITK_PP_IF(p(85, s), m, MITK_PP_TUPLE_EAT_2)(85, s) MITK_PP_IF(p(85, s), MITK_PP_FOR_85, MITK_PP_TUPLE_EAT_4)(o(85, s), p, o, m) # define MITK_PP_FOR_85_I(s, p, o, m) MITK_PP_IF(p(86, s), m, MITK_PP_TUPLE_EAT_2)(86, s) MITK_PP_IF(p(86, s), MITK_PP_FOR_86, MITK_PP_TUPLE_EAT_4)(o(86, s), p, o, m) # define MITK_PP_FOR_86_I(s, p, o, m) MITK_PP_IF(p(87, s), m, MITK_PP_TUPLE_EAT_2)(87, s) MITK_PP_IF(p(87, s), MITK_PP_FOR_87, MITK_PP_TUPLE_EAT_4)(o(87, s), p, o, m) # define MITK_PP_FOR_87_I(s, p, o, m) MITK_PP_IF(p(88, s), m, MITK_PP_TUPLE_EAT_2)(88, s) MITK_PP_IF(p(88, s), MITK_PP_FOR_88, MITK_PP_TUPLE_EAT_4)(o(88, s), p, o, m) # define MITK_PP_FOR_88_I(s, p, o, m) MITK_PP_IF(p(89, s), m, MITK_PP_TUPLE_EAT_2)(89, s) MITK_PP_IF(p(89, s), MITK_PP_FOR_89, MITK_PP_TUPLE_EAT_4)(o(89, s), p, o, m) # define MITK_PP_FOR_89_I(s, p, o, m) MITK_PP_IF(p(90, s), m, MITK_PP_TUPLE_EAT_2)(90, s) MITK_PP_IF(p(90, s), MITK_PP_FOR_90, MITK_PP_TUPLE_EAT_4)(o(90, s), p, o, m) # define MITK_PP_FOR_90_I(s, p, o, m) MITK_PP_IF(p(91, s), m, MITK_PP_TUPLE_EAT_2)(91, s) MITK_PP_IF(p(91, s), MITK_PP_FOR_91, MITK_PP_TUPLE_EAT_4)(o(91, s), p, o, m) # define MITK_PP_FOR_91_I(s, p, o, m) MITK_PP_IF(p(92, s), m, MITK_PP_TUPLE_EAT_2)(92, s) MITK_PP_IF(p(92, s), MITK_PP_FOR_92, MITK_PP_TUPLE_EAT_4)(o(92, s), p, o, m) # define MITK_PP_FOR_92_I(s, p, o, m) MITK_PP_IF(p(93, s), m, MITK_PP_TUPLE_EAT_2)(93, s) MITK_PP_IF(p(93, s), MITK_PP_FOR_93, MITK_PP_TUPLE_EAT_4)(o(93, s), p, o, m) # define MITK_PP_FOR_93_I(s, p, o, m) MITK_PP_IF(p(94, s), m, MITK_PP_TUPLE_EAT_2)(94, s) MITK_PP_IF(p(94, s), MITK_PP_FOR_94, MITK_PP_TUPLE_EAT_4)(o(94, s), p, o, m) # define MITK_PP_FOR_94_I(s, p, o, m) MITK_PP_IF(p(95, s), m, MITK_PP_TUPLE_EAT_2)(95, s) MITK_PP_IF(p(95, s), MITK_PP_FOR_95, MITK_PP_TUPLE_EAT_4)(o(95, s), p, o, m) # define MITK_PP_FOR_95_I(s, p, o, m) MITK_PP_IF(p(96, s), m, MITK_PP_TUPLE_EAT_2)(96, s) MITK_PP_IF(p(96, s), MITK_PP_FOR_96, MITK_PP_TUPLE_EAT_4)(o(96, s), p, o, m) # define MITK_PP_FOR_96_I(s, p, o, m) MITK_PP_IF(p(97, s), m, MITK_PP_TUPLE_EAT_2)(97, s) MITK_PP_IF(p(97, s), MITK_PP_FOR_97, MITK_PP_TUPLE_EAT_4)(o(97, s), p, o, m) # define MITK_PP_FOR_97_I(s, p, o, m) MITK_PP_IF(p(98, s), m, MITK_PP_TUPLE_EAT_2)(98, s) MITK_PP_IF(p(98, s), MITK_PP_FOR_98, MITK_PP_TUPLE_EAT_4)(o(98, s), p, o, m) # define MITK_PP_FOR_98_I(s, p, o, m) MITK_PP_IF(p(99, s), m, MITK_PP_TUPLE_EAT_2)(99, s) MITK_PP_IF(p(99, s), MITK_PP_FOR_99, MITK_PP_TUPLE_EAT_4)(o(99, s), p, o, m) # define MITK_PP_FOR_99_I(s, p, o, m) MITK_PP_IF(p(100, s), m, MITK_PP_TUPLE_EAT_2)(100, s) MITK_PP_IF(p(100, s), MITK_PP_FOR_100, MITK_PP_TUPLE_EAT_4)(o(100, s), p, o, m) # define MITK_PP_FOR_100_I(s, p, o, m) MITK_PP_IF(p(101, s), m, MITK_PP_TUPLE_EAT_2)(101, s) MITK_PP_IF(p(101, s), MITK_PP_FOR_101, MITK_PP_TUPLE_EAT_4)(o(101, s), p, o, m) # define MITK_PP_FOR_101_I(s, p, o, m) MITK_PP_IF(p(102, s), m, MITK_PP_TUPLE_EAT_2)(102, s) MITK_PP_IF(p(102, s), MITK_PP_FOR_102, MITK_PP_TUPLE_EAT_4)(o(102, s), p, o, m) # define MITK_PP_FOR_102_I(s, p, o, m) MITK_PP_IF(p(103, s), m, MITK_PP_TUPLE_EAT_2)(103, s) MITK_PP_IF(p(103, s), MITK_PP_FOR_103, MITK_PP_TUPLE_EAT_4)(o(103, s), p, o, m) # define MITK_PP_FOR_103_I(s, p, o, m) MITK_PP_IF(p(104, s), m, MITK_PP_TUPLE_EAT_2)(104, s) MITK_PP_IF(p(104, s), MITK_PP_FOR_104, MITK_PP_TUPLE_EAT_4)(o(104, s), p, o, m) # define MITK_PP_FOR_104_I(s, p, o, m) MITK_PP_IF(p(105, s), m, MITK_PP_TUPLE_EAT_2)(105, s) MITK_PP_IF(p(105, s), MITK_PP_FOR_105, MITK_PP_TUPLE_EAT_4)(o(105, s), p, o, m) # define MITK_PP_FOR_105_I(s, p, o, m) MITK_PP_IF(p(106, s), m, MITK_PP_TUPLE_EAT_2)(106, s) MITK_PP_IF(p(106, s), MITK_PP_FOR_106, MITK_PP_TUPLE_EAT_4)(o(106, s), p, o, m) # define MITK_PP_FOR_106_I(s, p, o, m) MITK_PP_IF(p(107, s), m, MITK_PP_TUPLE_EAT_2)(107, s) MITK_PP_IF(p(107, s), MITK_PP_FOR_107, MITK_PP_TUPLE_EAT_4)(o(107, s), p, o, m) # define MITK_PP_FOR_107_I(s, p, o, m) MITK_PP_IF(p(108, s), m, MITK_PP_TUPLE_EAT_2)(108, s) MITK_PP_IF(p(108, s), MITK_PP_FOR_108, MITK_PP_TUPLE_EAT_4)(o(108, s), p, o, m) # define MITK_PP_FOR_108_I(s, p, o, m) MITK_PP_IF(p(109, s), m, MITK_PP_TUPLE_EAT_2)(109, s) MITK_PP_IF(p(109, s), MITK_PP_FOR_109, MITK_PP_TUPLE_EAT_4)(o(109, s), p, o, m) # define MITK_PP_FOR_109_I(s, p, o, m) MITK_PP_IF(p(110, s), m, MITK_PP_TUPLE_EAT_2)(110, s) MITK_PP_IF(p(110, s), MITK_PP_FOR_110, MITK_PP_TUPLE_EAT_4)(o(110, s), p, o, m) # define MITK_PP_FOR_110_I(s, p, o, m) MITK_PP_IF(p(111, s), m, MITK_PP_TUPLE_EAT_2)(111, s) MITK_PP_IF(p(111, s), MITK_PP_FOR_111, MITK_PP_TUPLE_EAT_4)(o(111, s), p, o, m) # define MITK_PP_FOR_111_I(s, p, o, m) MITK_PP_IF(p(112, s), m, MITK_PP_TUPLE_EAT_2)(112, s) MITK_PP_IF(p(112, s), MITK_PP_FOR_112, MITK_PP_TUPLE_EAT_4)(o(112, s), p, o, m) # define MITK_PP_FOR_112_I(s, p, o, m) MITK_PP_IF(p(113, s), m, MITK_PP_TUPLE_EAT_2)(113, s) MITK_PP_IF(p(113, s), MITK_PP_FOR_113, MITK_PP_TUPLE_EAT_4)(o(113, s), p, o, m) # define MITK_PP_FOR_113_I(s, p, o, m) MITK_PP_IF(p(114, s), m, MITK_PP_TUPLE_EAT_2)(114, s) MITK_PP_IF(p(114, s), MITK_PP_FOR_114, MITK_PP_TUPLE_EAT_4)(o(114, s), p, o, m) # define MITK_PP_FOR_114_I(s, p, o, m) MITK_PP_IF(p(115, s), m, MITK_PP_TUPLE_EAT_2)(115, s) MITK_PP_IF(p(115, s), MITK_PP_FOR_115, MITK_PP_TUPLE_EAT_4)(o(115, s), p, o, m) # define MITK_PP_FOR_115_I(s, p, o, m) MITK_PP_IF(p(116, s), m, MITK_PP_TUPLE_EAT_2)(116, s) MITK_PP_IF(p(116, s), MITK_PP_FOR_116, MITK_PP_TUPLE_EAT_4)(o(116, s), p, o, m) # define MITK_PP_FOR_116_I(s, p, o, m) MITK_PP_IF(p(117, s), m, MITK_PP_TUPLE_EAT_2)(117, s) MITK_PP_IF(p(117, s), MITK_PP_FOR_117, MITK_PP_TUPLE_EAT_4)(o(117, s), p, o, m) # define MITK_PP_FOR_117_I(s, p, o, m) MITK_PP_IF(p(118, s), m, MITK_PP_TUPLE_EAT_2)(118, s) MITK_PP_IF(p(118, s), MITK_PP_FOR_118, MITK_PP_TUPLE_EAT_4)(o(118, s), p, o, m) # define MITK_PP_FOR_118_I(s, p, o, m) MITK_PP_IF(p(119, s), m, MITK_PP_TUPLE_EAT_2)(119, s) MITK_PP_IF(p(119, s), MITK_PP_FOR_119, MITK_PP_TUPLE_EAT_4)(o(119, s), p, o, m) # define MITK_PP_FOR_119_I(s, p, o, m) MITK_PP_IF(p(120, s), m, MITK_PP_TUPLE_EAT_2)(120, s) MITK_PP_IF(p(120, s), MITK_PP_FOR_120, MITK_PP_TUPLE_EAT_4)(o(120, s), p, o, m) # define MITK_PP_FOR_120_I(s, p, o, m) MITK_PP_IF(p(121, s), m, MITK_PP_TUPLE_EAT_2)(121, s) MITK_PP_IF(p(121, s), MITK_PP_FOR_121, MITK_PP_TUPLE_EAT_4)(o(121, s), p, o, m) # define MITK_PP_FOR_121_I(s, p, o, m) MITK_PP_IF(p(122, s), m, MITK_PP_TUPLE_EAT_2)(122, s) MITK_PP_IF(p(122, s), MITK_PP_FOR_122, MITK_PP_TUPLE_EAT_4)(o(122, s), p, o, m) # define MITK_PP_FOR_122_I(s, p, o, m) MITK_PP_IF(p(123, s), m, MITK_PP_TUPLE_EAT_2)(123, s) MITK_PP_IF(p(123, s), MITK_PP_FOR_123, MITK_PP_TUPLE_EAT_4)(o(123, s), p, o, m) # define MITK_PP_FOR_123_I(s, p, o, m) MITK_PP_IF(p(124, s), m, MITK_PP_TUPLE_EAT_2)(124, s) MITK_PP_IF(p(124, s), MITK_PP_FOR_124, MITK_PP_TUPLE_EAT_4)(o(124, s), p, o, m) # define MITK_PP_FOR_124_I(s, p, o, m) MITK_PP_IF(p(125, s), m, MITK_PP_TUPLE_EAT_2)(125, s) MITK_PP_IF(p(125, s), MITK_PP_FOR_125, MITK_PP_TUPLE_EAT_4)(o(125, s), p, o, m) # define MITK_PP_FOR_125_I(s, p, o, m) MITK_PP_IF(p(126, s), m, MITK_PP_TUPLE_EAT_2)(126, s) MITK_PP_IF(p(126, s), MITK_PP_FOR_126, MITK_PP_TUPLE_EAT_4)(o(126, s), p, o, m) # define MITK_PP_FOR_126_I(s, p, o, m) MITK_PP_IF(p(127, s), m, MITK_PP_TUPLE_EAT_2)(127, s) MITK_PP_IF(p(127, s), MITK_PP_FOR_127, MITK_PP_TUPLE_EAT_4)(o(127, s), p, o, m) # define MITK_PP_FOR_127_I(s, p, o, m) MITK_PP_IF(p(128, s), m, MITK_PP_TUPLE_EAT_2)(128, s) MITK_PP_IF(p(128, s), MITK_PP_FOR_128, MITK_PP_TUPLE_EAT_4)(o(128, s), p, o, m) # define MITK_PP_FOR_128_I(s, p, o, m) MITK_PP_IF(p(129, s), m, MITK_PP_TUPLE_EAT_2)(129, s) MITK_PP_IF(p(129, s), MITK_PP_FOR_129, MITK_PP_TUPLE_EAT_4)(o(129, s), p, o, m) # define MITK_PP_FOR_129_I(s, p, o, m) MITK_PP_IF(p(130, s), m, MITK_PP_TUPLE_EAT_2)(130, s) MITK_PP_IF(p(130, s), MITK_PP_FOR_130, MITK_PP_TUPLE_EAT_4)(o(130, s), p, o, m) # define MITK_PP_FOR_130_I(s, p, o, m) MITK_PP_IF(p(131, s), m, MITK_PP_TUPLE_EAT_2)(131, s) MITK_PP_IF(p(131, s), MITK_PP_FOR_131, MITK_PP_TUPLE_EAT_4)(o(131, s), p, o, m) # define MITK_PP_FOR_131_I(s, p, o, m) MITK_PP_IF(p(132, s), m, MITK_PP_TUPLE_EAT_2)(132, s) MITK_PP_IF(p(132, s), MITK_PP_FOR_132, MITK_PP_TUPLE_EAT_4)(o(132, s), p, o, m) # define MITK_PP_FOR_132_I(s, p, o, m) MITK_PP_IF(p(133, s), m, MITK_PP_TUPLE_EAT_2)(133, s) MITK_PP_IF(p(133, s), MITK_PP_FOR_133, MITK_PP_TUPLE_EAT_4)(o(133, s), p, o, m) # define MITK_PP_FOR_133_I(s, p, o, m) MITK_PP_IF(p(134, s), m, MITK_PP_TUPLE_EAT_2)(134, s) MITK_PP_IF(p(134, s), MITK_PP_FOR_134, MITK_PP_TUPLE_EAT_4)(o(134, s), p, o, m) # define MITK_PP_FOR_134_I(s, p, o, m) MITK_PP_IF(p(135, s), m, MITK_PP_TUPLE_EAT_2)(135, s) MITK_PP_IF(p(135, s), MITK_PP_FOR_135, MITK_PP_TUPLE_EAT_4)(o(135, s), p, o, m) # define MITK_PP_FOR_135_I(s, p, o, m) MITK_PP_IF(p(136, s), m, MITK_PP_TUPLE_EAT_2)(136, s) MITK_PP_IF(p(136, s), MITK_PP_FOR_136, MITK_PP_TUPLE_EAT_4)(o(136, s), p, o, m) # define MITK_PP_FOR_136_I(s, p, o, m) MITK_PP_IF(p(137, s), m, MITK_PP_TUPLE_EAT_2)(137, s) MITK_PP_IF(p(137, s), MITK_PP_FOR_137, MITK_PP_TUPLE_EAT_4)(o(137, s), p, o, m) # define MITK_PP_FOR_137_I(s, p, o, m) MITK_PP_IF(p(138, s), m, MITK_PP_TUPLE_EAT_2)(138, s) MITK_PP_IF(p(138, s), MITK_PP_FOR_138, MITK_PP_TUPLE_EAT_4)(o(138, s), p, o, m) # define MITK_PP_FOR_138_I(s, p, o, m) MITK_PP_IF(p(139, s), m, MITK_PP_TUPLE_EAT_2)(139, s) MITK_PP_IF(p(139, s), MITK_PP_FOR_139, MITK_PP_TUPLE_EAT_4)(o(139, s), p, o, m) # define MITK_PP_FOR_139_I(s, p, o, m) MITK_PP_IF(p(140, s), m, MITK_PP_TUPLE_EAT_2)(140, s) MITK_PP_IF(p(140, s), MITK_PP_FOR_140, MITK_PP_TUPLE_EAT_4)(o(140, s), p, o, m) # define MITK_PP_FOR_140_I(s, p, o, m) MITK_PP_IF(p(141, s), m, MITK_PP_TUPLE_EAT_2)(141, s) MITK_PP_IF(p(141, s), MITK_PP_FOR_141, MITK_PP_TUPLE_EAT_4)(o(141, s), p, o, m) # define MITK_PP_FOR_141_I(s, p, o, m) MITK_PP_IF(p(142, s), m, MITK_PP_TUPLE_EAT_2)(142, s) MITK_PP_IF(p(142, s), MITK_PP_FOR_142, MITK_PP_TUPLE_EAT_4)(o(142, s), p, o, m) # define MITK_PP_FOR_142_I(s, p, o, m) MITK_PP_IF(p(143, s), m, MITK_PP_TUPLE_EAT_2)(143, s) MITK_PP_IF(p(143, s), MITK_PP_FOR_143, MITK_PP_TUPLE_EAT_4)(o(143, s), p, o, m) # define MITK_PP_FOR_143_I(s, p, o, m) MITK_PP_IF(p(144, s), m, MITK_PP_TUPLE_EAT_2)(144, s) MITK_PP_IF(p(144, s), MITK_PP_FOR_144, MITK_PP_TUPLE_EAT_4)(o(144, s), p, o, m) # define MITK_PP_FOR_144_I(s, p, o, m) MITK_PP_IF(p(145, s), m, MITK_PP_TUPLE_EAT_2)(145, s) MITK_PP_IF(p(145, s), MITK_PP_FOR_145, MITK_PP_TUPLE_EAT_4)(o(145, s), p, o, m) # define MITK_PP_FOR_145_I(s, p, o, m) MITK_PP_IF(p(146, s), m, MITK_PP_TUPLE_EAT_2)(146, s) MITK_PP_IF(p(146, s), MITK_PP_FOR_146, MITK_PP_TUPLE_EAT_4)(o(146, s), p, o, m) # define MITK_PP_FOR_146_I(s, p, o, m) MITK_PP_IF(p(147, s), m, MITK_PP_TUPLE_EAT_2)(147, s) MITK_PP_IF(p(147, s), MITK_PP_FOR_147, MITK_PP_TUPLE_EAT_4)(o(147, s), p, o, m) # define MITK_PP_FOR_147_I(s, p, o, m) MITK_PP_IF(p(148, s), m, MITK_PP_TUPLE_EAT_2)(148, s) MITK_PP_IF(p(148, s), MITK_PP_FOR_148, MITK_PP_TUPLE_EAT_4)(o(148, s), p, o, m) # define MITK_PP_FOR_148_I(s, p, o, m) MITK_PP_IF(p(149, s), m, MITK_PP_TUPLE_EAT_2)(149, s) MITK_PP_IF(p(149, s), MITK_PP_FOR_149, MITK_PP_TUPLE_EAT_4)(o(149, s), p, o, m) # define MITK_PP_FOR_149_I(s, p, o, m) MITK_PP_IF(p(150, s), m, MITK_PP_TUPLE_EAT_2)(150, s) MITK_PP_IF(p(150, s), MITK_PP_FOR_150, MITK_PP_TUPLE_EAT_4)(o(150, s), p, o, m) # define MITK_PP_FOR_150_I(s, p, o, m) MITK_PP_IF(p(151, s), m, MITK_PP_TUPLE_EAT_2)(151, s) MITK_PP_IF(p(151, s), MITK_PP_FOR_151, MITK_PP_TUPLE_EAT_4)(o(151, s), p, o, m) # define MITK_PP_FOR_151_I(s, p, o, m) MITK_PP_IF(p(152, s), m, MITK_PP_TUPLE_EAT_2)(152, s) MITK_PP_IF(p(152, s), MITK_PP_FOR_152, MITK_PP_TUPLE_EAT_4)(o(152, s), p, o, m) # define MITK_PP_FOR_152_I(s, p, o, m) MITK_PP_IF(p(153, s), m, MITK_PP_TUPLE_EAT_2)(153, s) MITK_PP_IF(p(153, s), MITK_PP_FOR_153, MITK_PP_TUPLE_EAT_4)(o(153, s), p, o, m) # define MITK_PP_FOR_153_I(s, p, o, m) MITK_PP_IF(p(154, s), m, MITK_PP_TUPLE_EAT_2)(154, s) MITK_PP_IF(p(154, s), MITK_PP_FOR_154, MITK_PP_TUPLE_EAT_4)(o(154, s), p, o, m) # define MITK_PP_FOR_154_I(s, p, o, m) MITK_PP_IF(p(155, s), m, MITK_PP_TUPLE_EAT_2)(155, s) MITK_PP_IF(p(155, s), MITK_PP_FOR_155, MITK_PP_TUPLE_EAT_4)(o(155, s), p, o, m) # define MITK_PP_FOR_155_I(s, p, o, m) MITK_PP_IF(p(156, s), m, MITK_PP_TUPLE_EAT_2)(156, s) MITK_PP_IF(p(156, s), MITK_PP_FOR_156, MITK_PP_TUPLE_EAT_4)(o(156, s), p, o, m) # define MITK_PP_FOR_156_I(s, p, o, m) MITK_PP_IF(p(157, s), m, MITK_PP_TUPLE_EAT_2)(157, s) MITK_PP_IF(p(157, s), MITK_PP_FOR_157, MITK_PP_TUPLE_EAT_4)(o(157, s), p, o, m) # define MITK_PP_FOR_157_I(s, p, o, m) MITK_PP_IF(p(158, s), m, MITK_PP_TUPLE_EAT_2)(158, s) MITK_PP_IF(p(158, s), MITK_PP_FOR_158, MITK_PP_TUPLE_EAT_4)(o(158, s), p, o, m) # define MITK_PP_FOR_158_I(s, p, o, m) MITK_PP_IF(p(159, s), m, MITK_PP_TUPLE_EAT_2)(159, s) MITK_PP_IF(p(159, s), MITK_PP_FOR_159, MITK_PP_TUPLE_EAT_4)(o(159, s), p, o, m) # define MITK_PP_FOR_159_I(s, p, o, m) MITK_PP_IF(p(160, s), m, MITK_PP_TUPLE_EAT_2)(160, s) MITK_PP_IF(p(160, s), MITK_PP_FOR_160, MITK_PP_TUPLE_EAT_4)(o(160, s), p, o, m) # define MITK_PP_FOR_160_I(s, p, o, m) MITK_PP_IF(p(161, s), m, MITK_PP_TUPLE_EAT_2)(161, s) MITK_PP_IF(p(161, s), MITK_PP_FOR_161, MITK_PP_TUPLE_EAT_4)(o(161, s), p, o, m) # define MITK_PP_FOR_161_I(s, p, o, m) MITK_PP_IF(p(162, s), m, MITK_PP_TUPLE_EAT_2)(162, s) MITK_PP_IF(p(162, s), MITK_PP_FOR_162, MITK_PP_TUPLE_EAT_4)(o(162, s), p, o, m) # define MITK_PP_FOR_162_I(s, p, o, m) MITK_PP_IF(p(163, s), m, MITK_PP_TUPLE_EAT_2)(163, s) MITK_PP_IF(p(163, s), MITK_PP_FOR_163, MITK_PP_TUPLE_EAT_4)(o(163, s), p, o, m) # define MITK_PP_FOR_163_I(s, p, o, m) MITK_PP_IF(p(164, s), m, MITK_PP_TUPLE_EAT_2)(164, s) MITK_PP_IF(p(164, s), MITK_PP_FOR_164, MITK_PP_TUPLE_EAT_4)(o(164, s), p, o, m) # define MITK_PP_FOR_164_I(s, p, o, m) MITK_PP_IF(p(165, s), m, MITK_PP_TUPLE_EAT_2)(165, s) MITK_PP_IF(p(165, s), MITK_PP_FOR_165, MITK_PP_TUPLE_EAT_4)(o(165, s), p, o, m) # define MITK_PP_FOR_165_I(s, p, o, m) MITK_PP_IF(p(166, s), m, MITK_PP_TUPLE_EAT_2)(166, s) MITK_PP_IF(p(166, s), MITK_PP_FOR_166, MITK_PP_TUPLE_EAT_4)(o(166, s), p, o, m) # define MITK_PP_FOR_166_I(s, p, o, m) MITK_PP_IF(p(167, s), m, MITK_PP_TUPLE_EAT_2)(167, s) MITK_PP_IF(p(167, s), MITK_PP_FOR_167, MITK_PP_TUPLE_EAT_4)(o(167, s), p, o, m) # define MITK_PP_FOR_167_I(s, p, o, m) MITK_PP_IF(p(168, s), m, MITK_PP_TUPLE_EAT_2)(168, s) MITK_PP_IF(p(168, s), MITK_PP_FOR_168, MITK_PP_TUPLE_EAT_4)(o(168, s), p, o, m) # define MITK_PP_FOR_168_I(s, p, o, m) MITK_PP_IF(p(169, s), m, MITK_PP_TUPLE_EAT_2)(169, s) MITK_PP_IF(p(169, s), MITK_PP_FOR_169, MITK_PP_TUPLE_EAT_4)(o(169, s), p, o, m) # define MITK_PP_FOR_169_I(s, p, o, m) MITK_PP_IF(p(170, s), m, MITK_PP_TUPLE_EAT_2)(170, s) MITK_PP_IF(p(170, s), MITK_PP_FOR_170, MITK_PP_TUPLE_EAT_4)(o(170, s), p, o, m) # define MITK_PP_FOR_170_I(s, p, o, m) MITK_PP_IF(p(171, s), m, MITK_PP_TUPLE_EAT_2)(171, s) MITK_PP_IF(p(171, s), MITK_PP_FOR_171, MITK_PP_TUPLE_EAT_4)(o(171, s), p, o, m) # define MITK_PP_FOR_171_I(s, p, o, m) MITK_PP_IF(p(172, s), m, MITK_PP_TUPLE_EAT_2)(172, s) MITK_PP_IF(p(172, s), MITK_PP_FOR_172, MITK_PP_TUPLE_EAT_4)(o(172, s), p, o, m) # define MITK_PP_FOR_172_I(s, p, o, m) MITK_PP_IF(p(173, s), m, MITK_PP_TUPLE_EAT_2)(173, s) MITK_PP_IF(p(173, s), MITK_PP_FOR_173, MITK_PP_TUPLE_EAT_4)(o(173, s), p, o, m) # define MITK_PP_FOR_173_I(s, p, o, m) MITK_PP_IF(p(174, s), m, MITK_PP_TUPLE_EAT_2)(174, s) MITK_PP_IF(p(174, s), MITK_PP_FOR_174, MITK_PP_TUPLE_EAT_4)(o(174, s), p, o, m) # define MITK_PP_FOR_174_I(s, p, o, m) MITK_PP_IF(p(175, s), m, MITK_PP_TUPLE_EAT_2)(175, s) MITK_PP_IF(p(175, s), MITK_PP_FOR_175, MITK_PP_TUPLE_EAT_4)(o(175, s), p, o, m) # define MITK_PP_FOR_175_I(s, p, o, m) MITK_PP_IF(p(176, s), m, MITK_PP_TUPLE_EAT_2)(176, s) MITK_PP_IF(p(176, s), MITK_PP_FOR_176, MITK_PP_TUPLE_EAT_4)(o(176, s), p, o, m) # define MITK_PP_FOR_176_I(s, p, o, m) MITK_PP_IF(p(177, s), m, MITK_PP_TUPLE_EAT_2)(177, s) MITK_PP_IF(p(177, s), MITK_PP_FOR_177, MITK_PP_TUPLE_EAT_4)(o(177, s), p, o, m) # define MITK_PP_FOR_177_I(s, p, o, m) MITK_PP_IF(p(178, s), m, MITK_PP_TUPLE_EAT_2)(178, s) MITK_PP_IF(p(178, s), MITK_PP_FOR_178, MITK_PP_TUPLE_EAT_4)(o(178, s), p, o, m) # define MITK_PP_FOR_178_I(s, p, o, m) MITK_PP_IF(p(179, s), m, MITK_PP_TUPLE_EAT_2)(179, s) MITK_PP_IF(p(179, s), MITK_PP_FOR_179, MITK_PP_TUPLE_EAT_4)(o(179, s), p, o, m) # define MITK_PP_FOR_179_I(s, p, o, m) MITK_PP_IF(p(180, s), m, MITK_PP_TUPLE_EAT_2)(180, s) MITK_PP_IF(p(180, s), MITK_PP_FOR_180, MITK_PP_TUPLE_EAT_4)(o(180, s), p, o, m) # define MITK_PP_FOR_180_I(s, p, o, m) MITK_PP_IF(p(181, s), m, MITK_PP_TUPLE_EAT_2)(181, s) MITK_PP_IF(p(181, s), MITK_PP_FOR_181, MITK_PP_TUPLE_EAT_4)(o(181, s), p, o, m) # define MITK_PP_FOR_181_I(s, p, o, m) MITK_PP_IF(p(182, s), m, MITK_PP_TUPLE_EAT_2)(182, s) MITK_PP_IF(p(182, s), MITK_PP_FOR_182, MITK_PP_TUPLE_EAT_4)(o(182, s), p, o, m) # define MITK_PP_FOR_182_I(s, p, o, m) MITK_PP_IF(p(183, s), m, MITK_PP_TUPLE_EAT_2)(183, s) MITK_PP_IF(p(183, s), MITK_PP_FOR_183, MITK_PP_TUPLE_EAT_4)(o(183, s), p, o, m) # define MITK_PP_FOR_183_I(s, p, o, m) MITK_PP_IF(p(184, s), m, MITK_PP_TUPLE_EAT_2)(184, s) MITK_PP_IF(p(184, s), MITK_PP_FOR_184, MITK_PP_TUPLE_EAT_4)(o(184, s), p, o, m) # define MITK_PP_FOR_184_I(s, p, o, m) MITK_PP_IF(p(185, s), m, MITK_PP_TUPLE_EAT_2)(185, s) MITK_PP_IF(p(185, s), MITK_PP_FOR_185, MITK_PP_TUPLE_EAT_4)(o(185, s), p, o, m) # define MITK_PP_FOR_185_I(s, p, o, m) MITK_PP_IF(p(186, s), m, MITK_PP_TUPLE_EAT_2)(186, s) MITK_PP_IF(p(186, s), MITK_PP_FOR_186, MITK_PP_TUPLE_EAT_4)(o(186, s), p, o, m) # define MITK_PP_FOR_186_I(s, p, o, m) MITK_PP_IF(p(187, s), m, MITK_PP_TUPLE_EAT_2)(187, s) MITK_PP_IF(p(187, s), MITK_PP_FOR_187, MITK_PP_TUPLE_EAT_4)(o(187, s), p, o, m) # define MITK_PP_FOR_187_I(s, p, o, m) MITK_PP_IF(p(188, s), m, MITK_PP_TUPLE_EAT_2)(188, s) MITK_PP_IF(p(188, s), MITK_PP_FOR_188, MITK_PP_TUPLE_EAT_4)(o(188, s), p, o, m) # define MITK_PP_FOR_188_I(s, p, o, m) MITK_PP_IF(p(189, s), m, MITK_PP_TUPLE_EAT_2)(189, s) MITK_PP_IF(p(189, s), MITK_PP_FOR_189, MITK_PP_TUPLE_EAT_4)(o(189, s), p, o, m) # define MITK_PP_FOR_189_I(s, p, o, m) MITK_PP_IF(p(190, s), m, MITK_PP_TUPLE_EAT_2)(190, s) MITK_PP_IF(p(190, s), MITK_PP_FOR_190, MITK_PP_TUPLE_EAT_4)(o(190, s), p, o, m) # define MITK_PP_FOR_190_I(s, p, o, m) MITK_PP_IF(p(191, s), m, MITK_PP_TUPLE_EAT_2)(191, s) MITK_PP_IF(p(191, s), MITK_PP_FOR_191, MITK_PP_TUPLE_EAT_4)(o(191, s), p, o, m) # define MITK_PP_FOR_191_I(s, p, o, m) MITK_PP_IF(p(192, s), m, MITK_PP_TUPLE_EAT_2)(192, s) MITK_PP_IF(p(192, s), MITK_PP_FOR_192, MITK_PP_TUPLE_EAT_4)(o(192, s), p, o, m) # define MITK_PP_FOR_192_I(s, p, o, m) MITK_PP_IF(p(193, s), m, MITK_PP_TUPLE_EAT_2)(193, s) MITK_PP_IF(p(193, s), MITK_PP_FOR_193, MITK_PP_TUPLE_EAT_4)(o(193, s), p, o, m) # define MITK_PP_FOR_193_I(s, p, o, m) MITK_PP_IF(p(194, s), m, MITK_PP_TUPLE_EAT_2)(194, s) MITK_PP_IF(p(194, s), MITK_PP_FOR_194, MITK_PP_TUPLE_EAT_4)(o(194, s), p, o, m) # define MITK_PP_FOR_194_I(s, p, o, m) MITK_PP_IF(p(195, s), m, MITK_PP_TUPLE_EAT_2)(195, s) MITK_PP_IF(p(195, s), MITK_PP_FOR_195, MITK_PP_TUPLE_EAT_4)(o(195, s), p, o, m) # define MITK_PP_FOR_195_I(s, p, o, m) MITK_PP_IF(p(196, s), m, MITK_PP_TUPLE_EAT_2)(196, s) MITK_PP_IF(p(196, s), MITK_PP_FOR_196, MITK_PP_TUPLE_EAT_4)(o(196, s), p, o, m) # define MITK_PP_FOR_196_I(s, p, o, m) MITK_PP_IF(p(197, s), m, MITK_PP_TUPLE_EAT_2)(197, s) MITK_PP_IF(p(197, s), MITK_PP_FOR_197, MITK_PP_TUPLE_EAT_4)(o(197, s), p, o, m) # define MITK_PP_FOR_197_I(s, p, o, m) MITK_PP_IF(p(198, s), m, MITK_PP_TUPLE_EAT_2)(198, s) MITK_PP_IF(p(198, s), MITK_PP_FOR_198, MITK_PP_TUPLE_EAT_4)(o(198, s), p, o, m) # define MITK_PP_FOR_198_I(s, p, o, m) MITK_PP_IF(p(199, s), m, MITK_PP_TUPLE_EAT_2)(199, s) MITK_PP_IF(p(199, s), MITK_PP_FOR_199, MITK_PP_TUPLE_EAT_4)(o(199, s), p, o, m) # define MITK_PP_FOR_199_I(s, p, o, m) MITK_PP_IF(p(200, s), m, MITK_PP_TUPLE_EAT_2)(200, s) MITK_PP_IF(p(200, s), MITK_PP_FOR_200, MITK_PP_TUPLE_EAT_4)(o(200, s), p, o, m) # define MITK_PP_FOR_200_I(s, p, o, m) MITK_PP_IF(p(201, s), m, MITK_PP_TUPLE_EAT_2)(201, s) MITK_PP_IF(p(201, s), MITK_PP_FOR_201, MITK_PP_TUPLE_EAT_4)(o(201, s), p, o, m) # define MITK_PP_FOR_201_I(s, p, o, m) MITK_PP_IF(p(202, s), m, MITK_PP_TUPLE_EAT_2)(202, s) MITK_PP_IF(p(202, s), MITK_PP_FOR_202, MITK_PP_TUPLE_EAT_4)(o(202, s), p, o, m) # define MITK_PP_FOR_202_I(s, p, o, m) MITK_PP_IF(p(203, s), m, MITK_PP_TUPLE_EAT_2)(203, s) MITK_PP_IF(p(203, s), MITK_PP_FOR_203, MITK_PP_TUPLE_EAT_4)(o(203, s), p, o, m) # define MITK_PP_FOR_203_I(s, p, o, m) MITK_PP_IF(p(204, s), m, MITK_PP_TUPLE_EAT_2)(204, s) MITK_PP_IF(p(204, s), MITK_PP_FOR_204, MITK_PP_TUPLE_EAT_4)(o(204, s), p, o, m) # define MITK_PP_FOR_204_I(s, p, o, m) MITK_PP_IF(p(205, s), m, MITK_PP_TUPLE_EAT_2)(205, s) MITK_PP_IF(p(205, s), MITK_PP_FOR_205, MITK_PP_TUPLE_EAT_4)(o(205, s), p, o, m) # define MITK_PP_FOR_205_I(s, p, o, m) MITK_PP_IF(p(206, s), m, MITK_PP_TUPLE_EAT_2)(206, s) MITK_PP_IF(p(206, s), MITK_PP_FOR_206, MITK_PP_TUPLE_EAT_4)(o(206, s), p, o, m) # define MITK_PP_FOR_206_I(s, p, o, m) MITK_PP_IF(p(207, s), m, MITK_PP_TUPLE_EAT_2)(207, s) MITK_PP_IF(p(207, s), MITK_PP_FOR_207, MITK_PP_TUPLE_EAT_4)(o(207, s), p, o, m) # define MITK_PP_FOR_207_I(s, p, o, m) MITK_PP_IF(p(208, s), m, MITK_PP_TUPLE_EAT_2)(208, s) MITK_PP_IF(p(208, s), MITK_PP_FOR_208, MITK_PP_TUPLE_EAT_4)(o(208, s), p, o, m) # define MITK_PP_FOR_208_I(s, p, o, m) MITK_PP_IF(p(209, s), m, MITK_PP_TUPLE_EAT_2)(209, s) MITK_PP_IF(p(209, s), MITK_PP_FOR_209, MITK_PP_TUPLE_EAT_4)(o(209, s), p, o, m) # define MITK_PP_FOR_209_I(s, p, o, m) MITK_PP_IF(p(210, s), m, MITK_PP_TUPLE_EAT_2)(210, s) MITK_PP_IF(p(210, s), MITK_PP_FOR_210, MITK_PP_TUPLE_EAT_4)(o(210, s), p, o, m) # define MITK_PP_FOR_210_I(s, p, o, m) MITK_PP_IF(p(211, s), m, MITK_PP_TUPLE_EAT_2)(211, s) MITK_PP_IF(p(211, s), MITK_PP_FOR_211, MITK_PP_TUPLE_EAT_4)(o(211, s), p, o, m) # define MITK_PP_FOR_211_I(s, p, o, m) MITK_PP_IF(p(212, s), m, MITK_PP_TUPLE_EAT_2)(212, s) MITK_PP_IF(p(212, s), MITK_PP_FOR_212, MITK_PP_TUPLE_EAT_4)(o(212, s), p, o, m) # define MITK_PP_FOR_212_I(s, p, o, m) MITK_PP_IF(p(213, s), m, MITK_PP_TUPLE_EAT_2)(213, s) MITK_PP_IF(p(213, s), MITK_PP_FOR_213, MITK_PP_TUPLE_EAT_4)(o(213, s), p, o, m) # define MITK_PP_FOR_213_I(s, p, o, m) MITK_PP_IF(p(214, s), m, MITK_PP_TUPLE_EAT_2)(214, s) MITK_PP_IF(p(214, s), MITK_PP_FOR_214, MITK_PP_TUPLE_EAT_4)(o(214, s), p, o, m) # define MITK_PP_FOR_214_I(s, p, o, m) MITK_PP_IF(p(215, s), m, MITK_PP_TUPLE_EAT_2)(215, s) MITK_PP_IF(p(215, s), MITK_PP_FOR_215, MITK_PP_TUPLE_EAT_4)(o(215, s), p, o, m) # define MITK_PP_FOR_215_I(s, p, o, m) MITK_PP_IF(p(216, s), m, MITK_PP_TUPLE_EAT_2)(216, s) MITK_PP_IF(p(216, s), MITK_PP_FOR_216, MITK_PP_TUPLE_EAT_4)(o(216, s), p, o, m) # define MITK_PP_FOR_216_I(s, p, o, m) MITK_PP_IF(p(217, s), m, MITK_PP_TUPLE_EAT_2)(217, s) MITK_PP_IF(p(217, s), MITK_PP_FOR_217, MITK_PP_TUPLE_EAT_4)(o(217, s), p, o, m) # define MITK_PP_FOR_217_I(s, p, o, m) MITK_PP_IF(p(218, s), m, MITK_PP_TUPLE_EAT_2)(218, s) MITK_PP_IF(p(218, s), MITK_PP_FOR_218, MITK_PP_TUPLE_EAT_4)(o(218, s), p, o, m) # define MITK_PP_FOR_218_I(s, p, o, m) MITK_PP_IF(p(219, s), m, MITK_PP_TUPLE_EAT_2)(219, s) MITK_PP_IF(p(219, s), MITK_PP_FOR_219, MITK_PP_TUPLE_EAT_4)(o(219, s), p, o, m) # define MITK_PP_FOR_219_I(s, p, o, m) MITK_PP_IF(p(220, s), m, MITK_PP_TUPLE_EAT_2)(220, s) MITK_PP_IF(p(220, s), MITK_PP_FOR_220, MITK_PP_TUPLE_EAT_4)(o(220, s), p, o, m) # define MITK_PP_FOR_220_I(s, p, o, m) MITK_PP_IF(p(221, s), m, MITK_PP_TUPLE_EAT_2)(221, s) MITK_PP_IF(p(221, s), MITK_PP_FOR_221, MITK_PP_TUPLE_EAT_4)(o(221, s), p, o, m) # define MITK_PP_FOR_221_I(s, p, o, m) MITK_PP_IF(p(222, s), m, MITK_PP_TUPLE_EAT_2)(222, s) MITK_PP_IF(p(222, s), MITK_PP_FOR_222, MITK_PP_TUPLE_EAT_4)(o(222, s), p, o, m) # define MITK_PP_FOR_222_I(s, p, o, m) MITK_PP_IF(p(223, s), m, MITK_PP_TUPLE_EAT_2)(223, s) MITK_PP_IF(p(223, s), MITK_PP_FOR_223, MITK_PP_TUPLE_EAT_4)(o(223, s), p, o, m) # define MITK_PP_FOR_223_I(s, p, o, m) MITK_PP_IF(p(224, s), m, MITK_PP_TUPLE_EAT_2)(224, s) MITK_PP_IF(p(224, s), MITK_PP_FOR_224, MITK_PP_TUPLE_EAT_4)(o(224, s), p, o, m) # define MITK_PP_FOR_224_I(s, p, o, m) MITK_PP_IF(p(225, s), m, MITK_PP_TUPLE_EAT_2)(225, s) MITK_PP_IF(p(225, s), MITK_PP_FOR_225, MITK_PP_TUPLE_EAT_4)(o(225, s), p, o, m) # define MITK_PP_FOR_225_I(s, p, o, m) MITK_PP_IF(p(226, s), m, MITK_PP_TUPLE_EAT_2)(226, s) MITK_PP_IF(p(226, s), MITK_PP_FOR_226, MITK_PP_TUPLE_EAT_4)(o(226, s), p, o, m) # define MITK_PP_FOR_226_I(s, p, o, m) MITK_PP_IF(p(227, s), m, MITK_PP_TUPLE_EAT_2)(227, s) MITK_PP_IF(p(227, s), MITK_PP_FOR_227, MITK_PP_TUPLE_EAT_4)(o(227, s), p, o, m) # define MITK_PP_FOR_227_I(s, p, o, m) MITK_PP_IF(p(228, s), m, MITK_PP_TUPLE_EAT_2)(228, s) MITK_PP_IF(p(228, s), MITK_PP_FOR_228, MITK_PP_TUPLE_EAT_4)(o(228, s), p, o, m) # define MITK_PP_FOR_228_I(s, p, o, m) MITK_PP_IF(p(229, s), m, MITK_PP_TUPLE_EAT_2)(229, s) MITK_PP_IF(p(229, s), MITK_PP_FOR_229, MITK_PP_TUPLE_EAT_4)(o(229, s), p, o, m) # define MITK_PP_FOR_229_I(s, p, o, m) MITK_PP_IF(p(230, s), m, MITK_PP_TUPLE_EAT_2)(230, s) MITK_PP_IF(p(230, s), MITK_PP_FOR_230, MITK_PP_TUPLE_EAT_4)(o(230, s), p, o, m) # define MITK_PP_FOR_230_I(s, p, o, m) MITK_PP_IF(p(231, s), m, MITK_PP_TUPLE_EAT_2)(231, s) MITK_PP_IF(p(231, s), MITK_PP_FOR_231, MITK_PP_TUPLE_EAT_4)(o(231, s), p, o, m) # define MITK_PP_FOR_231_I(s, p, o, m) MITK_PP_IF(p(232, s), m, MITK_PP_TUPLE_EAT_2)(232, s) MITK_PP_IF(p(232, s), MITK_PP_FOR_232, MITK_PP_TUPLE_EAT_4)(o(232, s), p, o, m) # define MITK_PP_FOR_232_I(s, p, o, m) MITK_PP_IF(p(233, s), m, MITK_PP_TUPLE_EAT_2)(233, s) MITK_PP_IF(p(233, s), MITK_PP_FOR_233, MITK_PP_TUPLE_EAT_4)(o(233, s), p, o, m) # define MITK_PP_FOR_233_I(s, p, o, m) MITK_PP_IF(p(234, s), m, MITK_PP_TUPLE_EAT_2)(234, s) MITK_PP_IF(p(234, s), MITK_PP_FOR_234, MITK_PP_TUPLE_EAT_4)(o(234, s), p, o, m) # define MITK_PP_FOR_234_I(s, p, o, m) MITK_PP_IF(p(235, s), m, MITK_PP_TUPLE_EAT_2)(235, s) MITK_PP_IF(p(235, s), MITK_PP_FOR_235, MITK_PP_TUPLE_EAT_4)(o(235, s), p, o, m) # define MITK_PP_FOR_235_I(s, p, o, m) MITK_PP_IF(p(236, s), m, MITK_PP_TUPLE_EAT_2)(236, s) MITK_PP_IF(p(236, s), MITK_PP_FOR_236, MITK_PP_TUPLE_EAT_4)(o(236, s), p, o, m) # define MITK_PP_FOR_236_I(s, p, o, m) MITK_PP_IF(p(237, s), m, MITK_PP_TUPLE_EAT_2)(237, s) MITK_PP_IF(p(237, s), MITK_PP_FOR_237, MITK_PP_TUPLE_EAT_4)(o(237, s), p, o, m) # define MITK_PP_FOR_237_I(s, p, o, m) MITK_PP_IF(p(238, s), m, MITK_PP_TUPLE_EAT_2)(238, s) MITK_PP_IF(p(238, s), MITK_PP_FOR_238, MITK_PP_TUPLE_EAT_4)(o(238, s), p, o, m) # define MITK_PP_FOR_238_I(s, p, o, m) MITK_PP_IF(p(239, s), m, MITK_PP_TUPLE_EAT_2)(239, s) MITK_PP_IF(p(239, s), MITK_PP_FOR_239, MITK_PP_TUPLE_EAT_4)(o(239, s), p, o, m) # define MITK_PP_FOR_239_I(s, p, o, m) MITK_PP_IF(p(240, s), m, MITK_PP_TUPLE_EAT_2)(240, s) MITK_PP_IF(p(240, s), MITK_PP_FOR_240, MITK_PP_TUPLE_EAT_4)(o(240, s), p, o, m) # define MITK_PP_FOR_240_I(s, p, o, m) MITK_PP_IF(p(241, s), m, MITK_PP_TUPLE_EAT_2)(241, s) MITK_PP_IF(p(241, s), MITK_PP_FOR_241, MITK_PP_TUPLE_EAT_4)(o(241, s), p, o, m) # define MITK_PP_FOR_241_I(s, p, o, m) MITK_PP_IF(p(242, s), m, MITK_PP_TUPLE_EAT_2)(242, s) MITK_PP_IF(p(242, s), MITK_PP_FOR_242, MITK_PP_TUPLE_EAT_4)(o(242, s), p, o, m) # define MITK_PP_FOR_242_I(s, p, o, m) MITK_PP_IF(p(243, s), m, MITK_PP_TUPLE_EAT_2)(243, s) MITK_PP_IF(p(243, s), MITK_PP_FOR_243, MITK_PP_TUPLE_EAT_4)(o(243, s), p, o, m) # define MITK_PP_FOR_243_I(s, p, o, m) MITK_PP_IF(p(244, s), m, MITK_PP_TUPLE_EAT_2)(244, s) MITK_PP_IF(p(244, s), MITK_PP_FOR_244, MITK_PP_TUPLE_EAT_4)(o(244, s), p, o, m) # define MITK_PP_FOR_244_I(s, p, o, m) MITK_PP_IF(p(245, s), m, MITK_PP_TUPLE_EAT_2)(245, s) MITK_PP_IF(p(245, s), MITK_PP_FOR_245, MITK_PP_TUPLE_EAT_4)(o(245, s), p, o, m) # define MITK_PP_FOR_245_I(s, p, o, m) MITK_PP_IF(p(246, s), m, MITK_PP_TUPLE_EAT_2)(246, s) MITK_PP_IF(p(246, s), MITK_PP_FOR_246, MITK_PP_TUPLE_EAT_4)(o(246, s), p, o, m) # define MITK_PP_FOR_246_I(s, p, o, m) MITK_PP_IF(p(247, s), m, MITK_PP_TUPLE_EAT_2)(247, s) MITK_PP_IF(p(247, s), MITK_PP_FOR_247, MITK_PP_TUPLE_EAT_4)(o(247, s), p, o, m) # define MITK_PP_FOR_247_I(s, p, o, m) MITK_PP_IF(p(248, s), m, MITK_PP_TUPLE_EAT_2)(248, s) MITK_PP_IF(p(248, s), MITK_PP_FOR_248, MITK_PP_TUPLE_EAT_4)(o(248, s), p, o, m) # define MITK_PP_FOR_248_I(s, p, o, m) MITK_PP_IF(p(249, s), m, MITK_PP_TUPLE_EAT_2)(249, s) MITK_PP_IF(p(249, s), MITK_PP_FOR_249, MITK_PP_TUPLE_EAT_4)(o(249, s), p, o, m) # define MITK_PP_FOR_249_I(s, p, o, m) MITK_PP_IF(p(250, s), m, MITK_PP_TUPLE_EAT_2)(250, s) MITK_PP_IF(p(250, s), MITK_PP_FOR_250, MITK_PP_TUPLE_EAT_4)(o(250, s), p, o, m) # define MITK_PP_FOR_250_I(s, p, o, m) MITK_PP_IF(p(251, s), m, MITK_PP_TUPLE_EAT_2)(251, s) MITK_PP_IF(p(251, s), MITK_PP_FOR_251, MITK_PP_TUPLE_EAT_4)(o(251, s), p, o, m) # define MITK_PP_FOR_251_I(s, p, o, m) MITK_PP_IF(p(252, s), m, MITK_PP_TUPLE_EAT_2)(252, s) MITK_PP_IF(p(252, s), MITK_PP_FOR_252, MITK_PP_TUPLE_EAT_4)(o(252, s), p, o, m) # define MITK_PP_FOR_252_I(s, p, o, m) MITK_PP_IF(p(253, s), m, MITK_PP_TUPLE_EAT_2)(253, s) MITK_PP_IF(p(253, s), MITK_PP_FOR_253, MITK_PP_TUPLE_EAT_4)(o(253, s), p, o, m) # define MITK_PP_FOR_253_I(s, p, o, m) MITK_PP_IF(p(254, s), m, MITK_PP_TUPLE_EAT_2)(254, s) MITK_PP_IF(p(254, s), MITK_PP_FOR_254, MITK_PP_TUPLE_EAT_4)(o(254, s), p, o, m) # define MITK_PP_FOR_254_I(s, p, o, m) MITK_PP_IF(p(255, s), m, MITK_PP_TUPLE_EAT_2)(255, s) MITK_PP_IF(p(255, s), MITK_PP_FOR_255, MITK_PP_TUPLE_EAT_4)(o(255, s), p, o, m) # define MITK_PP_FOR_255_I(s, p, o, m) MITK_PP_IF(p(256, s), m, MITK_PP_TUPLE_EAT_2)(256, s) MITK_PP_IF(p(256, s), MITK_PP_FOR_256, MITK_PP_TUPLE_EAT_4)(o(256, s), p, o, m) # define MITK_PP_FOR_256_I(s, p, o, m) MITK_PP_IF(p(257, s), m, MITK_PP_TUPLE_EAT_2)(257, s) MITK_PP_IF(p(257, s), MITK_PP_FOR_257, MITK_PP_TUPLE_EAT_4)(o(257, s), p, o, m) # # endif diff --git a/Core/Code/Algorithms/mitkPPRepetitionDetailFor.h b/Core/Code/Algorithms/mitkPPRepetitionDetailFor.h index e642ff7ffb..ee0bae00f2 100644 --- a/Core/Code/Algorithms/mitkPPRepetitionDetailFor.h +++ b/Core/Code/Algorithms/mitkPPRepetitionDetailFor.h @@ -1,536 +1,551 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP # define MITK_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP # # include "mitkPPControlExprIIf.h" # include "mitkPPControlIIf.h" # include "mitkPPLogicalBool.h" # include "mitkPPTupleEat.h" # # define MITK_PP_FOR_1(s, p, o, m) MITK_PP_FOR_1_C(MITK_PP_BOOL(p(2, s)), s, p, o, m) # define MITK_PP_FOR_2(s, p, o, m) MITK_PP_FOR_2_C(MITK_PP_BOOL(p(3, s)), s, p, o, m) # define MITK_PP_FOR_3(s, p, o, m) MITK_PP_FOR_3_C(MITK_PP_BOOL(p(4, s)), s, p, o, m) # define MITK_PP_FOR_4(s, p, o, m) MITK_PP_FOR_4_C(MITK_PP_BOOL(p(5, s)), s, p, o, m) # define MITK_PP_FOR_5(s, p, o, m) MITK_PP_FOR_5_C(MITK_PP_BOOL(p(6, s)), s, p, o, m) # define MITK_PP_FOR_6(s, p, o, m) MITK_PP_FOR_6_C(MITK_PP_BOOL(p(7, s)), s, p, o, m) # define MITK_PP_FOR_7(s, p, o, m) MITK_PP_FOR_7_C(MITK_PP_BOOL(p(8, s)), s, p, o, m) # define MITK_PP_FOR_8(s, p, o, m) MITK_PP_FOR_8_C(MITK_PP_BOOL(p(9, s)), s, p, o, m) # define MITK_PP_FOR_9(s, p, o, m) MITK_PP_FOR_9_C(MITK_PP_BOOL(p(10, s)), s, p, o, m) # define MITK_PP_FOR_10(s, p, o, m) MITK_PP_FOR_10_C(MITK_PP_BOOL(p(11, s)), s, p, o, m) # define MITK_PP_FOR_11(s, p, o, m) MITK_PP_FOR_11_C(MITK_PP_BOOL(p(12, s)), s, p, o, m) # define MITK_PP_FOR_12(s, p, o, m) MITK_PP_FOR_12_C(MITK_PP_BOOL(p(13, s)), s, p, o, m) # define MITK_PP_FOR_13(s, p, o, m) MITK_PP_FOR_13_C(MITK_PP_BOOL(p(14, s)), s, p, o, m) # define MITK_PP_FOR_14(s, p, o, m) MITK_PP_FOR_14_C(MITK_PP_BOOL(p(15, s)), s, p, o, m) # define MITK_PP_FOR_15(s, p, o, m) MITK_PP_FOR_15_C(MITK_PP_BOOL(p(16, s)), s, p, o, m) # define MITK_PP_FOR_16(s, p, o, m) MITK_PP_FOR_16_C(MITK_PP_BOOL(p(17, s)), s, p, o, m) # define MITK_PP_FOR_17(s, p, o, m) MITK_PP_FOR_17_C(MITK_PP_BOOL(p(18, s)), s, p, o, m) # define MITK_PP_FOR_18(s, p, o, m) MITK_PP_FOR_18_C(MITK_PP_BOOL(p(19, s)), s, p, o, m) # define MITK_PP_FOR_19(s, p, o, m) MITK_PP_FOR_19_C(MITK_PP_BOOL(p(20, s)), s, p, o, m) # define MITK_PP_FOR_20(s, p, o, m) MITK_PP_FOR_20_C(MITK_PP_BOOL(p(21, s)), s, p, o, m) # define MITK_PP_FOR_21(s, p, o, m) MITK_PP_FOR_21_C(MITK_PP_BOOL(p(22, s)), s, p, o, m) # define MITK_PP_FOR_22(s, p, o, m) MITK_PP_FOR_22_C(MITK_PP_BOOL(p(23, s)), s, p, o, m) # define MITK_PP_FOR_23(s, p, o, m) MITK_PP_FOR_23_C(MITK_PP_BOOL(p(24, s)), s, p, o, m) # define MITK_PP_FOR_24(s, p, o, m) MITK_PP_FOR_24_C(MITK_PP_BOOL(p(25, s)), s, p, o, m) # define MITK_PP_FOR_25(s, p, o, m) MITK_PP_FOR_25_C(MITK_PP_BOOL(p(26, s)), s, p, o, m) # define MITK_PP_FOR_26(s, p, o, m) MITK_PP_FOR_26_C(MITK_PP_BOOL(p(27, s)), s, p, o, m) # define MITK_PP_FOR_27(s, p, o, m) MITK_PP_FOR_27_C(MITK_PP_BOOL(p(28, s)), s, p, o, m) # define MITK_PP_FOR_28(s, p, o, m) MITK_PP_FOR_28_C(MITK_PP_BOOL(p(29, s)), s, p, o, m) # define MITK_PP_FOR_29(s, p, o, m) MITK_PP_FOR_29_C(MITK_PP_BOOL(p(30, s)), s, p, o, m) # define MITK_PP_FOR_30(s, p, o, m) MITK_PP_FOR_30_C(MITK_PP_BOOL(p(31, s)), s, p, o, m) # define MITK_PP_FOR_31(s, p, o, m) MITK_PP_FOR_31_C(MITK_PP_BOOL(p(32, s)), s, p, o, m) # define MITK_PP_FOR_32(s, p, o, m) MITK_PP_FOR_32_C(MITK_PP_BOOL(p(33, s)), s, p, o, m) # define MITK_PP_FOR_33(s, p, o, m) MITK_PP_FOR_33_C(MITK_PP_BOOL(p(34, s)), s, p, o, m) # define MITK_PP_FOR_34(s, p, o, m) MITK_PP_FOR_34_C(MITK_PP_BOOL(p(35, s)), s, p, o, m) # define MITK_PP_FOR_35(s, p, o, m) MITK_PP_FOR_35_C(MITK_PP_BOOL(p(36, s)), s, p, o, m) # define MITK_PP_FOR_36(s, p, o, m) MITK_PP_FOR_36_C(MITK_PP_BOOL(p(37, s)), s, p, o, m) # define MITK_PP_FOR_37(s, p, o, m) MITK_PP_FOR_37_C(MITK_PP_BOOL(p(38, s)), s, p, o, m) # define MITK_PP_FOR_38(s, p, o, m) MITK_PP_FOR_38_C(MITK_PP_BOOL(p(39, s)), s, p, o, m) # define MITK_PP_FOR_39(s, p, o, m) MITK_PP_FOR_39_C(MITK_PP_BOOL(p(40, s)), s, p, o, m) # define MITK_PP_FOR_40(s, p, o, m) MITK_PP_FOR_40_C(MITK_PP_BOOL(p(41, s)), s, p, o, m) # define MITK_PP_FOR_41(s, p, o, m) MITK_PP_FOR_41_C(MITK_PP_BOOL(p(42, s)), s, p, o, m) # define MITK_PP_FOR_42(s, p, o, m) MITK_PP_FOR_42_C(MITK_PP_BOOL(p(43, s)), s, p, o, m) # define MITK_PP_FOR_43(s, p, o, m) MITK_PP_FOR_43_C(MITK_PP_BOOL(p(44, s)), s, p, o, m) # define MITK_PP_FOR_44(s, p, o, m) MITK_PP_FOR_44_C(MITK_PP_BOOL(p(45, s)), s, p, o, m) # define MITK_PP_FOR_45(s, p, o, m) MITK_PP_FOR_45_C(MITK_PP_BOOL(p(46, s)), s, p, o, m) # define MITK_PP_FOR_46(s, p, o, m) MITK_PP_FOR_46_C(MITK_PP_BOOL(p(47, s)), s, p, o, m) # define MITK_PP_FOR_47(s, p, o, m) MITK_PP_FOR_47_C(MITK_PP_BOOL(p(48, s)), s, p, o, m) # define MITK_PP_FOR_48(s, p, o, m) MITK_PP_FOR_48_C(MITK_PP_BOOL(p(49, s)), s, p, o, m) # define MITK_PP_FOR_49(s, p, o, m) MITK_PP_FOR_49_C(MITK_PP_BOOL(p(50, s)), s, p, o, m) # define MITK_PP_FOR_50(s, p, o, m) MITK_PP_FOR_50_C(MITK_PP_BOOL(p(51, s)), s, p, o, m) # define MITK_PP_FOR_51(s, p, o, m) MITK_PP_FOR_51_C(MITK_PP_BOOL(p(52, s)), s, p, o, m) # define MITK_PP_FOR_52(s, p, o, m) MITK_PP_FOR_52_C(MITK_PP_BOOL(p(53, s)), s, p, o, m) # define MITK_PP_FOR_53(s, p, o, m) MITK_PP_FOR_53_C(MITK_PP_BOOL(p(54, s)), s, p, o, m) # define MITK_PP_FOR_54(s, p, o, m) MITK_PP_FOR_54_C(MITK_PP_BOOL(p(55, s)), s, p, o, m) # define MITK_PP_FOR_55(s, p, o, m) MITK_PP_FOR_55_C(MITK_PP_BOOL(p(56, s)), s, p, o, m) # define MITK_PP_FOR_56(s, p, o, m) MITK_PP_FOR_56_C(MITK_PP_BOOL(p(57, s)), s, p, o, m) # define MITK_PP_FOR_57(s, p, o, m) MITK_PP_FOR_57_C(MITK_PP_BOOL(p(58, s)), s, p, o, m) # define MITK_PP_FOR_58(s, p, o, m) MITK_PP_FOR_58_C(MITK_PP_BOOL(p(59, s)), s, p, o, m) # define MITK_PP_FOR_59(s, p, o, m) MITK_PP_FOR_59_C(MITK_PP_BOOL(p(60, s)), s, p, o, m) # define MITK_PP_FOR_60(s, p, o, m) MITK_PP_FOR_60_C(MITK_PP_BOOL(p(61, s)), s, p, o, m) # define MITK_PP_FOR_61(s, p, o, m) MITK_PP_FOR_61_C(MITK_PP_BOOL(p(62, s)), s, p, o, m) # define MITK_PP_FOR_62(s, p, o, m) MITK_PP_FOR_62_C(MITK_PP_BOOL(p(63, s)), s, p, o, m) # define MITK_PP_FOR_63(s, p, o, m) MITK_PP_FOR_63_C(MITK_PP_BOOL(p(64, s)), s, p, o, m) # define MITK_PP_FOR_64(s, p, o, m) MITK_PP_FOR_64_C(MITK_PP_BOOL(p(65, s)), s, p, o, m) # define MITK_PP_FOR_65(s, p, o, m) MITK_PP_FOR_65_C(MITK_PP_BOOL(p(66, s)), s, p, o, m) # define MITK_PP_FOR_66(s, p, o, m) MITK_PP_FOR_66_C(MITK_PP_BOOL(p(67, s)), s, p, o, m) # define MITK_PP_FOR_67(s, p, o, m) MITK_PP_FOR_67_C(MITK_PP_BOOL(p(68, s)), s, p, o, m) # define MITK_PP_FOR_68(s, p, o, m) MITK_PP_FOR_68_C(MITK_PP_BOOL(p(69, s)), s, p, o, m) # define MITK_PP_FOR_69(s, p, o, m) MITK_PP_FOR_69_C(MITK_PP_BOOL(p(70, s)), s, p, o, m) # define MITK_PP_FOR_70(s, p, o, m) MITK_PP_FOR_70_C(MITK_PP_BOOL(p(71, s)), s, p, o, m) # define MITK_PP_FOR_71(s, p, o, m) MITK_PP_FOR_71_C(MITK_PP_BOOL(p(72, s)), s, p, o, m) # define MITK_PP_FOR_72(s, p, o, m) MITK_PP_FOR_72_C(MITK_PP_BOOL(p(73, s)), s, p, o, m) # define MITK_PP_FOR_73(s, p, o, m) MITK_PP_FOR_73_C(MITK_PP_BOOL(p(74, s)), s, p, o, m) # define MITK_PP_FOR_74(s, p, o, m) MITK_PP_FOR_74_C(MITK_PP_BOOL(p(75, s)), s, p, o, m) # define MITK_PP_FOR_75(s, p, o, m) MITK_PP_FOR_75_C(MITK_PP_BOOL(p(76, s)), s, p, o, m) # define MITK_PP_FOR_76(s, p, o, m) MITK_PP_FOR_76_C(MITK_PP_BOOL(p(77, s)), s, p, o, m) # define MITK_PP_FOR_77(s, p, o, m) MITK_PP_FOR_77_C(MITK_PP_BOOL(p(78, s)), s, p, o, m) # define MITK_PP_FOR_78(s, p, o, m) MITK_PP_FOR_78_C(MITK_PP_BOOL(p(79, s)), s, p, o, m) # define MITK_PP_FOR_79(s, p, o, m) MITK_PP_FOR_79_C(MITK_PP_BOOL(p(80, s)), s, p, o, m) # define MITK_PP_FOR_80(s, p, o, m) MITK_PP_FOR_80_C(MITK_PP_BOOL(p(81, s)), s, p, o, m) # define MITK_PP_FOR_81(s, p, o, m) MITK_PP_FOR_81_C(MITK_PP_BOOL(p(82, s)), s, p, o, m) # define MITK_PP_FOR_82(s, p, o, m) MITK_PP_FOR_82_C(MITK_PP_BOOL(p(83, s)), s, p, o, m) # define MITK_PP_FOR_83(s, p, o, m) MITK_PP_FOR_83_C(MITK_PP_BOOL(p(84, s)), s, p, o, m) # define MITK_PP_FOR_84(s, p, o, m) MITK_PP_FOR_84_C(MITK_PP_BOOL(p(85, s)), s, p, o, m) # define MITK_PP_FOR_85(s, p, o, m) MITK_PP_FOR_85_C(MITK_PP_BOOL(p(86, s)), s, p, o, m) # define MITK_PP_FOR_86(s, p, o, m) MITK_PP_FOR_86_C(MITK_PP_BOOL(p(87, s)), s, p, o, m) # define MITK_PP_FOR_87(s, p, o, m) MITK_PP_FOR_87_C(MITK_PP_BOOL(p(88, s)), s, p, o, m) # define MITK_PP_FOR_88(s, p, o, m) MITK_PP_FOR_88_C(MITK_PP_BOOL(p(89, s)), s, p, o, m) # define MITK_PP_FOR_89(s, p, o, m) MITK_PP_FOR_89_C(MITK_PP_BOOL(p(90, s)), s, p, o, m) # define MITK_PP_FOR_90(s, p, o, m) MITK_PP_FOR_90_C(MITK_PP_BOOL(p(91, s)), s, p, o, m) # define MITK_PP_FOR_91(s, p, o, m) MITK_PP_FOR_91_C(MITK_PP_BOOL(p(92, s)), s, p, o, m) # define MITK_PP_FOR_92(s, p, o, m) MITK_PP_FOR_92_C(MITK_PP_BOOL(p(93, s)), s, p, o, m) # define MITK_PP_FOR_93(s, p, o, m) MITK_PP_FOR_93_C(MITK_PP_BOOL(p(94, s)), s, p, o, m) # define MITK_PP_FOR_94(s, p, o, m) MITK_PP_FOR_94_C(MITK_PP_BOOL(p(95, s)), s, p, o, m) # define MITK_PP_FOR_95(s, p, o, m) MITK_PP_FOR_95_C(MITK_PP_BOOL(p(96, s)), s, p, o, m) # define MITK_PP_FOR_96(s, p, o, m) MITK_PP_FOR_96_C(MITK_PP_BOOL(p(97, s)), s, p, o, m) # define MITK_PP_FOR_97(s, p, o, m) MITK_PP_FOR_97_C(MITK_PP_BOOL(p(98, s)), s, p, o, m) # define MITK_PP_FOR_98(s, p, o, m) MITK_PP_FOR_98_C(MITK_PP_BOOL(p(99, s)), s, p, o, m) # define MITK_PP_FOR_99(s, p, o, m) MITK_PP_FOR_99_C(MITK_PP_BOOL(p(100, s)), s, p, o, m) # define MITK_PP_FOR_100(s, p, o, m) MITK_PP_FOR_100_C(MITK_PP_BOOL(p(101, s)), s, p, o, m) # define MITK_PP_FOR_101(s, p, o, m) MITK_PP_FOR_101_C(MITK_PP_BOOL(p(102, s)), s, p, o, m) # define MITK_PP_FOR_102(s, p, o, m) MITK_PP_FOR_102_C(MITK_PP_BOOL(p(103, s)), s, p, o, m) # define MITK_PP_FOR_103(s, p, o, m) MITK_PP_FOR_103_C(MITK_PP_BOOL(p(104, s)), s, p, o, m) # define MITK_PP_FOR_104(s, p, o, m) MITK_PP_FOR_104_C(MITK_PP_BOOL(p(105, s)), s, p, o, m) # define MITK_PP_FOR_105(s, p, o, m) MITK_PP_FOR_105_C(MITK_PP_BOOL(p(106, s)), s, p, o, m) # define MITK_PP_FOR_106(s, p, o, m) MITK_PP_FOR_106_C(MITK_PP_BOOL(p(107, s)), s, p, o, m) # define MITK_PP_FOR_107(s, p, o, m) MITK_PP_FOR_107_C(MITK_PP_BOOL(p(108, s)), s, p, o, m) # define MITK_PP_FOR_108(s, p, o, m) MITK_PP_FOR_108_C(MITK_PP_BOOL(p(109, s)), s, p, o, m) # define MITK_PP_FOR_109(s, p, o, m) MITK_PP_FOR_109_C(MITK_PP_BOOL(p(110, s)), s, p, o, m) # define MITK_PP_FOR_110(s, p, o, m) MITK_PP_FOR_110_C(MITK_PP_BOOL(p(111, s)), s, p, o, m) # define MITK_PP_FOR_111(s, p, o, m) MITK_PP_FOR_111_C(MITK_PP_BOOL(p(112, s)), s, p, o, m) # define MITK_PP_FOR_112(s, p, o, m) MITK_PP_FOR_112_C(MITK_PP_BOOL(p(113, s)), s, p, o, m) # define MITK_PP_FOR_113(s, p, o, m) MITK_PP_FOR_113_C(MITK_PP_BOOL(p(114, s)), s, p, o, m) # define MITK_PP_FOR_114(s, p, o, m) MITK_PP_FOR_114_C(MITK_PP_BOOL(p(115, s)), s, p, o, m) # define MITK_PP_FOR_115(s, p, o, m) MITK_PP_FOR_115_C(MITK_PP_BOOL(p(116, s)), s, p, o, m) # define MITK_PP_FOR_116(s, p, o, m) MITK_PP_FOR_116_C(MITK_PP_BOOL(p(117, s)), s, p, o, m) # define MITK_PP_FOR_117(s, p, o, m) MITK_PP_FOR_117_C(MITK_PP_BOOL(p(118, s)), s, p, o, m) # define MITK_PP_FOR_118(s, p, o, m) MITK_PP_FOR_118_C(MITK_PP_BOOL(p(119, s)), s, p, o, m) # define MITK_PP_FOR_119(s, p, o, m) MITK_PP_FOR_119_C(MITK_PP_BOOL(p(120, s)), s, p, o, m) # define MITK_PP_FOR_120(s, p, o, m) MITK_PP_FOR_120_C(MITK_PP_BOOL(p(121, s)), s, p, o, m) # define MITK_PP_FOR_121(s, p, o, m) MITK_PP_FOR_121_C(MITK_PP_BOOL(p(122, s)), s, p, o, m) # define MITK_PP_FOR_122(s, p, o, m) MITK_PP_FOR_122_C(MITK_PP_BOOL(p(123, s)), s, p, o, m) # define MITK_PP_FOR_123(s, p, o, m) MITK_PP_FOR_123_C(MITK_PP_BOOL(p(124, s)), s, p, o, m) # define MITK_PP_FOR_124(s, p, o, m) MITK_PP_FOR_124_C(MITK_PP_BOOL(p(125, s)), s, p, o, m) # define MITK_PP_FOR_125(s, p, o, m) MITK_PP_FOR_125_C(MITK_PP_BOOL(p(126, s)), s, p, o, m) # define MITK_PP_FOR_126(s, p, o, m) MITK_PP_FOR_126_C(MITK_PP_BOOL(p(127, s)), s, p, o, m) # define MITK_PP_FOR_127(s, p, o, m) MITK_PP_FOR_127_C(MITK_PP_BOOL(p(128, s)), s, p, o, m) # define MITK_PP_FOR_128(s, p, o, m) MITK_PP_FOR_128_C(MITK_PP_BOOL(p(129, s)), s, p, o, m) # define MITK_PP_FOR_129(s, p, o, m) MITK_PP_FOR_129_C(MITK_PP_BOOL(p(130, s)), s, p, o, m) # define MITK_PP_FOR_130(s, p, o, m) MITK_PP_FOR_130_C(MITK_PP_BOOL(p(131, s)), s, p, o, m) # define MITK_PP_FOR_131(s, p, o, m) MITK_PP_FOR_131_C(MITK_PP_BOOL(p(132, s)), s, p, o, m) # define MITK_PP_FOR_132(s, p, o, m) MITK_PP_FOR_132_C(MITK_PP_BOOL(p(133, s)), s, p, o, m) # define MITK_PP_FOR_133(s, p, o, m) MITK_PP_FOR_133_C(MITK_PP_BOOL(p(134, s)), s, p, o, m) # define MITK_PP_FOR_134(s, p, o, m) MITK_PP_FOR_134_C(MITK_PP_BOOL(p(135, s)), s, p, o, m) # define MITK_PP_FOR_135(s, p, o, m) MITK_PP_FOR_135_C(MITK_PP_BOOL(p(136, s)), s, p, o, m) # define MITK_PP_FOR_136(s, p, o, m) MITK_PP_FOR_136_C(MITK_PP_BOOL(p(137, s)), s, p, o, m) # define MITK_PP_FOR_137(s, p, o, m) MITK_PP_FOR_137_C(MITK_PP_BOOL(p(138, s)), s, p, o, m) # define MITK_PP_FOR_138(s, p, o, m) MITK_PP_FOR_138_C(MITK_PP_BOOL(p(139, s)), s, p, o, m) # define MITK_PP_FOR_139(s, p, o, m) MITK_PP_FOR_139_C(MITK_PP_BOOL(p(140, s)), s, p, o, m) # define MITK_PP_FOR_140(s, p, o, m) MITK_PP_FOR_140_C(MITK_PP_BOOL(p(141, s)), s, p, o, m) # define MITK_PP_FOR_141(s, p, o, m) MITK_PP_FOR_141_C(MITK_PP_BOOL(p(142, s)), s, p, o, m) # define MITK_PP_FOR_142(s, p, o, m) MITK_PP_FOR_142_C(MITK_PP_BOOL(p(143, s)), s, p, o, m) # define MITK_PP_FOR_143(s, p, o, m) MITK_PP_FOR_143_C(MITK_PP_BOOL(p(144, s)), s, p, o, m) # define MITK_PP_FOR_144(s, p, o, m) MITK_PP_FOR_144_C(MITK_PP_BOOL(p(145, s)), s, p, o, m) # define MITK_PP_FOR_145(s, p, o, m) MITK_PP_FOR_145_C(MITK_PP_BOOL(p(146, s)), s, p, o, m) # define MITK_PP_FOR_146(s, p, o, m) MITK_PP_FOR_146_C(MITK_PP_BOOL(p(147, s)), s, p, o, m) # define MITK_PP_FOR_147(s, p, o, m) MITK_PP_FOR_147_C(MITK_PP_BOOL(p(148, s)), s, p, o, m) # define MITK_PP_FOR_148(s, p, o, m) MITK_PP_FOR_148_C(MITK_PP_BOOL(p(149, s)), s, p, o, m) # define MITK_PP_FOR_149(s, p, o, m) MITK_PP_FOR_149_C(MITK_PP_BOOL(p(150, s)), s, p, o, m) # define MITK_PP_FOR_150(s, p, o, m) MITK_PP_FOR_150_C(MITK_PP_BOOL(p(151, s)), s, p, o, m) # define MITK_PP_FOR_151(s, p, o, m) MITK_PP_FOR_151_C(MITK_PP_BOOL(p(152, s)), s, p, o, m) # define MITK_PP_FOR_152(s, p, o, m) MITK_PP_FOR_152_C(MITK_PP_BOOL(p(153, s)), s, p, o, m) # define MITK_PP_FOR_153(s, p, o, m) MITK_PP_FOR_153_C(MITK_PP_BOOL(p(154, s)), s, p, o, m) # define MITK_PP_FOR_154(s, p, o, m) MITK_PP_FOR_154_C(MITK_PP_BOOL(p(155, s)), s, p, o, m) # define MITK_PP_FOR_155(s, p, o, m) MITK_PP_FOR_155_C(MITK_PP_BOOL(p(156, s)), s, p, o, m) # define MITK_PP_FOR_156(s, p, o, m) MITK_PP_FOR_156_C(MITK_PP_BOOL(p(157, s)), s, p, o, m) # define MITK_PP_FOR_157(s, p, o, m) MITK_PP_FOR_157_C(MITK_PP_BOOL(p(158, s)), s, p, o, m) # define MITK_PP_FOR_158(s, p, o, m) MITK_PP_FOR_158_C(MITK_PP_BOOL(p(159, s)), s, p, o, m) # define MITK_PP_FOR_159(s, p, o, m) MITK_PP_FOR_159_C(MITK_PP_BOOL(p(160, s)), s, p, o, m) # define MITK_PP_FOR_160(s, p, o, m) MITK_PP_FOR_160_C(MITK_PP_BOOL(p(161, s)), s, p, o, m) # define MITK_PP_FOR_161(s, p, o, m) MITK_PP_FOR_161_C(MITK_PP_BOOL(p(162, s)), s, p, o, m) # define MITK_PP_FOR_162(s, p, o, m) MITK_PP_FOR_162_C(MITK_PP_BOOL(p(163, s)), s, p, o, m) # define MITK_PP_FOR_163(s, p, o, m) MITK_PP_FOR_163_C(MITK_PP_BOOL(p(164, s)), s, p, o, m) # define MITK_PP_FOR_164(s, p, o, m) MITK_PP_FOR_164_C(MITK_PP_BOOL(p(165, s)), s, p, o, m) # define MITK_PP_FOR_165(s, p, o, m) MITK_PP_FOR_165_C(MITK_PP_BOOL(p(166, s)), s, p, o, m) # define MITK_PP_FOR_166(s, p, o, m) MITK_PP_FOR_166_C(MITK_PP_BOOL(p(167, s)), s, p, o, m) # define MITK_PP_FOR_167(s, p, o, m) MITK_PP_FOR_167_C(MITK_PP_BOOL(p(168, s)), s, p, o, m) # define MITK_PP_FOR_168(s, p, o, m) MITK_PP_FOR_168_C(MITK_PP_BOOL(p(169, s)), s, p, o, m) # define MITK_PP_FOR_169(s, p, o, m) MITK_PP_FOR_169_C(MITK_PP_BOOL(p(170, s)), s, p, o, m) # define MITK_PP_FOR_170(s, p, o, m) MITK_PP_FOR_170_C(MITK_PP_BOOL(p(171, s)), s, p, o, m) # define MITK_PP_FOR_171(s, p, o, m) MITK_PP_FOR_171_C(MITK_PP_BOOL(p(172, s)), s, p, o, m) # define MITK_PP_FOR_172(s, p, o, m) MITK_PP_FOR_172_C(MITK_PP_BOOL(p(173, s)), s, p, o, m) # define MITK_PP_FOR_173(s, p, o, m) MITK_PP_FOR_173_C(MITK_PP_BOOL(p(174, s)), s, p, o, m) # define MITK_PP_FOR_174(s, p, o, m) MITK_PP_FOR_174_C(MITK_PP_BOOL(p(175, s)), s, p, o, m) # define MITK_PP_FOR_175(s, p, o, m) MITK_PP_FOR_175_C(MITK_PP_BOOL(p(176, s)), s, p, o, m) # define MITK_PP_FOR_176(s, p, o, m) MITK_PP_FOR_176_C(MITK_PP_BOOL(p(177, s)), s, p, o, m) # define MITK_PP_FOR_177(s, p, o, m) MITK_PP_FOR_177_C(MITK_PP_BOOL(p(178, s)), s, p, o, m) # define MITK_PP_FOR_178(s, p, o, m) MITK_PP_FOR_178_C(MITK_PP_BOOL(p(179, s)), s, p, o, m) # define MITK_PP_FOR_179(s, p, o, m) MITK_PP_FOR_179_C(MITK_PP_BOOL(p(180, s)), s, p, o, m) # define MITK_PP_FOR_180(s, p, o, m) MITK_PP_FOR_180_C(MITK_PP_BOOL(p(181, s)), s, p, o, m) # define MITK_PP_FOR_181(s, p, o, m) MITK_PP_FOR_181_C(MITK_PP_BOOL(p(182, s)), s, p, o, m) # define MITK_PP_FOR_182(s, p, o, m) MITK_PP_FOR_182_C(MITK_PP_BOOL(p(183, s)), s, p, o, m) # define MITK_PP_FOR_183(s, p, o, m) MITK_PP_FOR_183_C(MITK_PP_BOOL(p(184, s)), s, p, o, m) # define MITK_PP_FOR_184(s, p, o, m) MITK_PP_FOR_184_C(MITK_PP_BOOL(p(185, s)), s, p, o, m) # define MITK_PP_FOR_185(s, p, o, m) MITK_PP_FOR_185_C(MITK_PP_BOOL(p(186, s)), s, p, o, m) # define MITK_PP_FOR_186(s, p, o, m) MITK_PP_FOR_186_C(MITK_PP_BOOL(p(187, s)), s, p, o, m) # define MITK_PP_FOR_187(s, p, o, m) MITK_PP_FOR_187_C(MITK_PP_BOOL(p(188, s)), s, p, o, m) # define MITK_PP_FOR_188(s, p, o, m) MITK_PP_FOR_188_C(MITK_PP_BOOL(p(189, s)), s, p, o, m) # define MITK_PP_FOR_189(s, p, o, m) MITK_PP_FOR_189_C(MITK_PP_BOOL(p(190, s)), s, p, o, m) # define MITK_PP_FOR_190(s, p, o, m) MITK_PP_FOR_190_C(MITK_PP_BOOL(p(191, s)), s, p, o, m) # define MITK_PP_FOR_191(s, p, o, m) MITK_PP_FOR_191_C(MITK_PP_BOOL(p(192, s)), s, p, o, m) # define MITK_PP_FOR_192(s, p, o, m) MITK_PP_FOR_192_C(MITK_PP_BOOL(p(193, s)), s, p, o, m) # define MITK_PP_FOR_193(s, p, o, m) MITK_PP_FOR_193_C(MITK_PP_BOOL(p(194, s)), s, p, o, m) # define MITK_PP_FOR_194(s, p, o, m) MITK_PP_FOR_194_C(MITK_PP_BOOL(p(195, s)), s, p, o, m) # define MITK_PP_FOR_195(s, p, o, m) MITK_PP_FOR_195_C(MITK_PP_BOOL(p(196, s)), s, p, o, m) # define MITK_PP_FOR_196(s, p, o, m) MITK_PP_FOR_196_C(MITK_PP_BOOL(p(197, s)), s, p, o, m) # define MITK_PP_FOR_197(s, p, o, m) MITK_PP_FOR_197_C(MITK_PP_BOOL(p(198, s)), s, p, o, m) # define MITK_PP_FOR_198(s, p, o, m) MITK_PP_FOR_198_C(MITK_PP_BOOL(p(199, s)), s, p, o, m) # define MITK_PP_FOR_199(s, p, o, m) MITK_PP_FOR_199_C(MITK_PP_BOOL(p(200, s)), s, p, o, m) # define MITK_PP_FOR_200(s, p, o, m) MITK_PP_FOR_200_C(MITK_PP_BOOL(p(201, s)), s, p, o, m) # define MITK_PP_FOR_201(s, p, o, m) MITK_PP_FOR_201_C(MITK_PP_BOOL(p(202, s)), s, p, o, m) # define MITK_PP_FOR_202(s, p, o, m) MITK_PP_FOR_202_C(MITK_PP_BOOL(p(203, s)), s, p, o, m) # define MITK_PP_FOR_203(s, p, o, m) MITK_PP_FOR_203_C(MITK_PP_BOOL(p(204, s)), s, p, o, m) # define MITK_PP_FOR_204(s, p, o, m) MITK_PP_FOR_204_C(MITK_PP_BOOL(p(205, s)), s, p, o, m) # define MITK_PP_FOR_205(s, p, o, m) MITK_PP_FOR_205_C(MITK_PP_BOOL(p(206, s)), s, p, o, m) # define MITK_PP_FOR_206(s, p, o, m) MITK_PP_FOR_206_C(MITK_PP_BOOL(p(207, s)), s, p, o, m) # define MITK_PP_FOR_207(s, p, o, m) MITK_PP_FOR_207_C(MITK_PP_BOOL(p(208, s)), s, p, o, m) # define MITK_PP_FOR_208(s, p, o, m) MITK_PP_FOR_208_C(MITK_PP_BOOL(p(209, s)), s, p, o, m) # define MITK_PP_FOR_209(s, p, o, m) MITK_PP_FOR_209_C(MITK_PP_BOOL(p(210, s)), s, p, o, m) # define MITK_PP_FOR_210(s, p, o, m) MITK_PP_FOR_210_C(MITK_PP_BOOL(p(211, s)), s, p, o, m) # define MITK_PP_FOR_211(s, p, o, m) MITK_PP_FOR_211_C(MITK_PP_BOOL(p(212, s)), s, p, o, m) # define MITK_PP_FOR_212(s, p, o, m) MITK_PP_FOR_212_C(MITK_PP_BOOL(p(213, s)), s, p, o, m) # define MITK_PP_FOR_213(s, p, o, m) MITK_PP_FOR_213_C(MITK_PP_BOOL(p(214, s)), s, p, o, m) # define MITK_PP_FOR_214(s, p, o, m) MITK_PP_FOR_214_C(MITK_PP_BOOL(p(215, s)), s, p, o, m) # define MITK_PP_FOR_215(s, p, o, m) MITK_PP_FOR_215_C(MITK_PP_BOOL(p(216, s)), s, p, o, m) # define MITK_PP_FOR_216(s, p, o, m) MITK_PP_FOR_216_C(MITK_PP_BOOL(p(217, s)), s, p, o, m) # define MITK_PP_FOR_217(s, p, o, m) MITK_PP_FOR_217_C(MITK_PP_BOOL(p(218, s)), s, p, o, m) # define MITK_PP_FOR_218(s, p, o, m) MITK_PP_FOR_218_C(MITK_PP_BOOL(p(219, s)), s, p, o, m) # define MITK_PP_FOR_219(s, p, o, m) MITK_PP_FOR_219_C(MITK_PP_BOOL(p(220, s)), s, p, o, m) # define MITK_PP_FOR_220(s, p, o, m) MITK_PP_FOR_220_C(MITK_PP_BOOL(p(221, s)), s, p, o, m) # define MITK_PP_FOR_221(s, p, o, m) MITK_PP_FOR_221_C(MITK_PP_BOOL(p(222, s)), s, p, o, m) # define MITK_PP_FOR_222(s, p, o, m) MITK_PP_FOR_222_C(MITK_PP_BOOL(p(223, s)), s, p, o, m) # define MITK_PP_FOR_223(s, p, o, m) MITK_PP_FOR_223_C(MITK_PP_BOOL(p(224, s)), s, p, o, m) # define MITK_PP_FOR_224(s, p, o, m) MITK_PP_FOR_224_C(MITK_PP_BOOL(p(225, s)), s, p, o, m) # define MITK_PP_FOR_225(s, p, o, m) MITK_PP_FOR_225_C(MITK_PP_BOOL(p(226, s)), s, p, o, m) # define MITK_PP_FOR_226(s, p, o, m) MITK_PP_FOR_226_C(MITK_PP_BOOL(p(227, s)), s, p, o, m) # define MITK_PP_FOR_227(s, p, o, m) MITK_PP_FOR_227_C(MITK_PP_BOOL(p(228, s)), s, p, o, m) # define MITK_PP_FOR_228(s, p, o, m) MITK_PP_FOR_228_C(MITK_PP_BOOL(p(229, s)), s, p, o, m) # define MITK_PP_FOR_229(s, p, o, m) MITK_PP_FOR_229_C(MITK_PP_BOOL(p(230, s)), s, p, o, m) # define MITK_PP_FOR_230(s, p, o, m) MITK_PP_FOR_230_C(MITK_PP_BOOL(p(231, s)), s, p, o, m) # define MITK_PP_FOR_231(s, p, o, m) MITK_PP_FOR_231_C(MITK_PP_BOOL(p(232, s)), s, p, o, m) # define MITK_PP_FOR_232(s, p, o, m) MITK_PP_FOR_232_C(MITK_PP_BOOL(p(233, s)), s, p, o, m) # define MITK_PP_FOR_233(s, p, o, m) MITK_PP_FOR_233_C(MITK_PP_BOOL(p(234, s)), s, p, o, m) # define MITK_PP_FOR_234(s, p, o, m) MITK_PP_FOR_234_C(MITK_PP_BOOL(p(235, s)), s, p, o, m) # define MITK_PP_FOR_235(s, p, o, m) MITK_PP_FOR_235_C(MITK_PP_BOOL(p(236, s)), s, p, o, m) # define MITK_PP_FOR_236(s, p, o, m) MITK_PP_FOR_236_C(MITK_PP_BOOL(p(237, s)), s, p, o, m) # define MITK_PP_FOR_237(s, p, o, m) MITK_PP_FOR_237_C(MITK_PP_BOOL(p(238, s)), s, p, o, m) # define MITK_PP_FOR_238(s, p, o, m) MITK_PP_FOR_238_C(MITK_PP_BOOL(p(239, s)), s, p, o, m) # define MITK_PP_FOR_239(s, p, o, m) MITK_PP_FOR_239_C(MITK_PP_BOOL(p(240, s)), s, p, o, m) # define MITK_PP_FOR_240(s, p, o, m) MITK_PP_FOR_240_C(MITK_PP_BOOL(p(241, s)), s, p, o, m) # define MITK_PP_FOR_241(s, p, o, m) MITK_PP_FOR_241_C(MITK_PP_BOOL(p(242, s)), s, p, o, m) # define MITK_PP_FOR_242(s, p, o, m) MITK_PP_FOR_242_C(MITK_PP_BOOL(p(243, s)), s, p, o, m) # define MITK_PP_FOR_243(s, p, o, m) MITK_PP_FOR_243_C(MITK_PP_BOOL(p(244, s)), s, p, o, m) # define MITK_PP_FOR_244(s, p, o, m) MITK_PP_FOR_244_C(MITK_PP_BOOL(p(245, s)), s, p, o, m) # define MITK_PP_FOR_245(s, p, o, m) MITK_PP_FOR_245_C(MITK_PP_BOOL(p(246, s)), s, p, o, m) # define MITK_PP_FOR_246(s, p, o, m) MITK_PP_FOR_246_C(MITK_PP_BOOL(p(247, s)), s, p, o, m) # define MITK_PP_FOR_247(s, p, o, m) MITK_PP_FOR_247_C(MITK_PP_BOOL(p(248, s)), s, p, o, m) # define MITK_PP_FOR_248(s, p, o, m) MITK_PP_FOR_248_C(MITK_PP_BOOL(p(249, s)), s, p, o, m) # define MITK_PP_FOR_249(s, p, o, m) MITK_PP_FOR_249_C(MITK_PP_BOOL(p(250, s)), s, p, o, m) # define MITK_PP_FOR_250(s, p, o, m) MITK_PP_FOR_250_C(MITK_PP_BOOL(p(251, s)), s, p, o, m) # define MITK_PP_FOR_251(s, p, o, m) MITK_PP_FOR_251_C(MITK_PP_BOOL(p(252, s)), s, p, o, m) # define MITK_PP_FOR_252(s, p, o, m) MITK_PP_FOR_252_C(MITK_PP_BOOL(p(253, s)), s, p, o, m) # define MITK_PP_FOR_253(s, p, o, m) MITK_PP_FOR_253_C(MITK_PP_BOOL(p(254, s)), s, p, o, m) # define MITK_PP_FOR_254(s, p, o, m) MITK_PP_FOR_254_C(MITK_PP_BOOL(p(255, s)), s, p, o, m) # define MITK_PP_FOR_255(s, p, o, m) MITK_PP_FOR_255_C(MITK_PP_BOOL(p(256, s)), s, p, o, m) # define MITK_PP_FOR_256(s, p, o, m) MITK_PP_FOR_256_C(MITK_PP_BOOL(p(257, s)), s, p, o, m) # # define MITK_PP_FOR_1_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(2, s) MITK_PP_IIF(c, MITK_PP_FOR_2, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(2, s), p, o, m) # define MITK_PP_FOR_2_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(3, s) MITK_PP_IIF(c, MITK_PP_FOR_3, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(3, s), p, o, m) # define MITK_PP_FOR_3_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(4, s) MITK_PP_IIF(c, MITK_PP_FOR_4, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(4, s), p, o, m) # define MITK_PP_FOR_4_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(5, s) MITK_PP_IIF(c, MITK_PP_FOR_5, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(5, s), p, o, m) # define MITK_PP_FOR_5_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(6, s) MITK_PP_IIF(c, MITK_PP_FOR_6, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(6, s), p, o, m) # define MITK_PP_FOR_6_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(7, s) MITK_PP_IIF(c, MITK_PP_FOR_7, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(7, s), p, o, m) # define MITK_PP_FOR_7_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(8, s) MITK_PP_IIF(c, MITK_PP_FOR_8, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(8, s), p, o, m) # define MITK_PP_FOR_8_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(9, s) MITK_PP_IIF(c, MITK_PP_FOR_9, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(9, s), p, o, m) # define MITK_PP_FOR_9_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(10, s) MITK_PP_IIF(c, MITK_PP_FOR_10, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(10, s), p, o, m) # define MITK_PP_FOR_10_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(11, s) MITK_PP_IIF(c, MITK_PP_FOR_11, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(11, s), p, o, m) # define MITK_PP_FOR_11_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(12, s) MITK_PP_IIF(c, MITK_PP_FOR_12, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(12, s), p, o, m) # define MITK_PP_FOR_12_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(13, s) MITK_PP_IIF(c, MITK_PP_FOR_13, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(13, s), p, o, m) # define MITK_PP_FOR_13_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(14, s) MITK_PP_IIF(c, MITK_PP_FOR_14, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(14, s), p, o, m) # define MITK_PP_FOR_14_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(15, s) MITK_PP_IIF(c, MITK_PP_FOR_15, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(15, s), p, o, m) # define MITK_PP_FOR_15_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(16, s) MITK_PP_IIF(c, MITK_PP_FOR_16, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(16, s), p, o, m) # define MITK_PP_FOR_16_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(17, s) MITK_PP_IIF(c, MITK_PP_FOR_17, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(17, s), p, o, m) # define MITK_PP_FOR_17_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(18, s) MITK_PP_IIF(c, MITK_PP_FOR_18, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(18, s), p, o, m) # define MITK_PP_FOR_18_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(19, s) MITK_PP_IIF(c, MITK_PP_FOR_19, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(19, s), p, o, m) # define MITK_PP_FOR_19_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(20, s) MITK_PP_IIF(c, MITK_PP_FOR_20, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(20, s), p, o, m) # define MITK_PP_FOR_20_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(21, s) MITK_PP_IIF(c, MITK_PP_FOR_21, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(21, s), p, o, m) # define MITK_PP_FOR_21_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(22, s) MITK_PP_IIF(c, MITK_PP_FOR_22, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(22, s), p, o, m) # define MITK_PP_FOR_22_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(23, s) MITK_PP_IIF(c, MITK_PP_FOR_23, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(23, s), p, o, m) # define MITK_PP_FOR_23_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(24, s) MITK_PP_IIF(c, MITK_PP_FOR_24, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(24, s), p, o, m) # define MITK_PP_FOR_24_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(25, s) MITK_PP_IIF(c, MITK_PP_FOR_25, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(25, s), p, o, m) # define MITK_PP_FOR_25_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(26, s) MITK_PP_IIF(c, MITK_PP_FOR_26, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(26, s), p, o, m) # define MITK_PP_FOR_26_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(27, s) MITK_PP_IIF(c, MITK_PP_FOR_27, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(27, s), p, o, m) # define MITK_PP_FOR_27_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(28, s) MITK_PP_IIF(c, MITK_PP_FOR_28, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(28, s), p, o, m) # define MITK_PP_FOR_28_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(29, s) MITK_PP_IIF(c, MITK_PP_FOR_29, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(29, s), p, o, m) # define MITK_PP_FOR_29_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(30, s) MITK_PP_IIF(c, MITK_PP_FOR_30, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(30, s), p, o, m) # define MITK_PP_FOR_30_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(31, s) MITK_PP_IIF(c, MITK_PP_FOR_31, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(31, s), p, o, m) # define MITK_PP_FOR_31_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(32, s) MITK_PP_IIF(c, MITK_PP_FOR_32, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(32, s), p, o, m) # define MITK_PP_FOR_32_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(33, s) MITK_PP_IIF(c, MITK_PP_FOR_33, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(33, s), p, o, m) # define MITK_PP_FOR_33_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(34, s) MITK_PP_IIF(c, MITK_PP_FOR_34, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(34, s), p, o, m) # define MITK_PP_FOR_34_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(35, s) MITK_PP_IIF(c, MITK_PP_FOR_35, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(35, s), p, o, m) # define MITK_PP_FOR_35_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(36, s) MITK_PP_IIF(c, MITK_PP_FOR_36, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(36, s), p, o, m) # define MITK_PP_FOR_36_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(37, s) MITK_PP_IIF(c, MITK_PP_FOR_37, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(37, s), p, o, m) # define MITK_PP_FOR_37_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(38, s) MITK_PP_IIF(c, MITK_PP_FOR_38, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(38, s), p, o, m) # define MITK_PP_FOR_38_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(39, s) MITK_PP_IIF(c, MITK_PP_FOR_39, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(39, s), p, o, m) # define MITK_PP_FOR_39_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(40, s) MITK_PP_IIF(c, MITK_PP_FOR_40, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(40, s), p, o, m) # define MITK_PP_FOR_40_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(41, s) MITK_PP_IIF(c, MITK_PP_FOR_41, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(41, s), p, o, m) # define MITK_PP_FOR_41_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(42, s) MITK_PP_IIF(c, MITK_PP_FOR_42, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(42, s), p, o, m) # define MITK_PP_FOR_42_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(43, s) MITK_PP_IIF(c, MITK_PP_FOR_43, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(43, s), p, o, m) # define MITK_PP_FOR_43_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(44, s) MITK_PP_IIF(c, MITK_PP_FOR_44, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(44, s), p, o, m) # define MITK_PP_FOR_44_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(45, s) MITK_PP_IIF(c, MITK_PP_FOR_45, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(45, s), p, o, m) # define MITK_PP_FOR_45_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(46, s) MITK_PP_IIF(c, MITK_PP_FOR_46, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(46, s), p, o, m) # define MITK_PP_FOR_46_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(47, s) MITK_PP_IIF(c, MITK_PP_FOR_47, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(47, s), p, o, m) # define MITK_PP_FOR_47_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(48, s) MITK_PP_IIF(c, MITK_PP_FOR_48, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(48, s), p, o, m) # define MITK_PP_FOR_48_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(49, s) MITK_PP_IIF(c, MITK_PP_FOR_49, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(49, s), p, o, m) # define MITK_PP_FOR_49_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(50, s) MITK_PP_IIF(c, MITK_PP_FOR_50, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(50, s), p, o, m) # define MITK_PP_FOR_50_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(51, s) MITK_PP_IIF(c, MITK_PP_FOR_51, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(51, s), p, o, m) # define MITK_PP_FOR_51_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(52, s) MITK_PP_IIF(c, MITK_PP_FOR_52, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(52, s), p, o, m) # define MITK_PP_FOR_52_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(53, s) MITK_PP_IIF(c, MITK_PP_FOR_53, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(53, s), p, o, m) # define MITK_PP_FOR_53_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(54, s) MITK_PP_IIF(c, MITK_PP_FOR_54, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(54, s), p, o, m) # define MITK_PP_FOR_54_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(55, s) MITK_PP_IIF(c, MITK_PP_FOR_55, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(55, s), p, o, m) # define MITK_PP_FOR_55_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(56, s) MITK_PP_IIF(c, MITK_PP_FOR_56, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(56, s), p, o, m) # define MITK_PP_FOR_56_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(57, s) MITK_PP_IIF(c, MITK_PP_FOR_57, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(57, s), p, o, m) # define MITK_PP_FOR_57_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(58, s) MITK_PP_IIF(c, MITK_PP_FOR_58, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(58, s), p, o, m) # define MITK_PP_FOR_58_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(59, s) MITK_PP_IIF(c, MITK_PP_FOR_59, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(59, s), p, o, m) # define MITK_PP_FOR_59_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(60, s) MITK_PP_IIF(c, MITK_PP_FOR_60, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(60, s), p, o, m) # define MITK_PP_FOR_60_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(61, s) MITK_PP_IIF(c, MITK_PP_FOR_61, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(61, s), p, o, m) # define MITK_PP_FOR_61_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(62, s) MITK_PP_IIF(c, MITK_PP_FOR_62, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(62, s), p, o, m) # define MITK_PP_FOR_62_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(63, s) MITK_PP_IIF(c, MITK_PP_FOR_63, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(63, s), p, o, m) # define MITK_PP_FOR_63_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(64, s) MITK_PP_IIF(c, MITK_PP_FOR_64, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(64, s), p, o, m) # define MITK_PP_FOR_64_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(65, s) MITK_PP_IIF(c, MITK_PP_FOR_65, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(65, s), p, o, m) # define MITK_PP_FOR_65_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(66, s) MITK_PP_IIF(c, MITK_PP_FOR_66, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(66, s), p, o, m) # define MITK_PP_FOR_66_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(67, s) MITK_PP_IIF(c, MITK_PP_FOR_67, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(67, s), p, o, m) # define MITK_PP_FOR_67_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(68, s) MITK_PP_IIF(c, MITK_PP_FOR_68, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(68, s), p, o, m) # define MITK_PP_FOR_68_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(69, s) MITK_PP_IIF(c, MITK_PP_FOR_69, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(69, s), p, o, m) # define MITK_PP_FOR_69_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(70, s) MITK_PP_IIF(c, MITK_PP_FOR_70, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(70, s), p, o, m) # define MITK_PP_FOR_70_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(71, s) MITK_PP_IIF(c, MITK_PP_FOR_71, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(71, s), p, o, m) # define MITK_PP_FOR_71_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(72, s) MITK_PP_IIF(c, MITK_PP_FOR_72, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(72, s), p, o, m) # define MITK_PP_FOR_72_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(73, s) MITK_PP_IIF(c, MITK_PP_FOR_73, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(73, s), p, o, m) # define MITK_PP_FOR_73_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(74, s) MITK_PP_IIF(c, MITK_PP_FOR_74, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(74, s), p, o, m) # define MITK_PP_FOR_74_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(75, s) MITK_PP_IIF(c, MITK_PP_FOR_75, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(75, s), p, o, m) # define MITK_PP_FOR_75_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(76, s) MITK_PP_IIF(c, MITK_PP_FOR_76, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(76, s), p, o, m) # define MITK_PP_FOR_76_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(77, s) MITK_PP_IIF(c, MITK_PP_FOR_77, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(77, s), p, o, m) # define MITK_PP_FOR_77_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(78, s) MITK_PP_IIF(c, MITK_PP_FOR_78, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(78, s), p, o, m) # define MITK_PP_FOR_78_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(79, s) MITK_PP_IIF(c, MITK_PP_FOR_79, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(79, s), p, o, m) # define MITK_PP_FOR_79_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(80, s) MITK_PP_IIF(c, MITK_PP_FOR_80, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(80, s), p, o, m) # define MITK_PP_FOR_80_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(81, s) MITK_PP_IIF(c, MITK_PP_FOR_81, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(81, s), p, o, m) # define MITK_PP_FOR_81_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(82, s) MITK_PP_IIF(c, MITK_PP_FOR_82, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(82, s), p, o, m) # define MITK_PP_FOR_82_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(83, s) MITK_PP_IIF(c, MITK_PP_FOR_83, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(83, s), p, o, m) # define MITK_PP_FOR_83_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(84, s) MITK_PP_IIF(c, MITK_PP_FOR_84, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(84, s), p, o, m) # define MITK_PP_FOR_84_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(85, s) MITK_PP_IIF(c, MITK_PP_FOR_85, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(85, s), p, o, m) # define MITK_PP_FOR_85_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(86, s) MITK_PP_IIF(c, MITK_PP_FOR_86, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(86, s), p, o, m) # define MITK_PP_FOR_86_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(87, s) MITK_PP_IIF(c, MITK_PP_FOR_87, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(87, s), p, o, m) # define MITK_PP_FOR_87_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(88, s) MITK_PP_IIF(c, MITK_PP_FOR_88, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(88, s), p, o, m) # define MITK_PP_FOR_88_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(89, s) MITK_PP_IIF(c, MITK_PP_FOR_89, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(89, s), p, o, m) # define MITK_PP_FOR_89_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(90, s) MITK_PP_IIF(c, MITK_PP_FOR_90, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(90, s), p, o, m) # define MITK_PP_FOR_90_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(91, s) MITK_PP_IIF(c, MITK_PP_FOR_91, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(91, s), p, o, m) # define MITK_PP_FOR_91_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(92, s) MITK_PP_IIF(c, MITK_PP_FOR_92, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(92, s), p, o, m) # define MITK_PP_FOR_92_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(93, s) MITK_PP_IIF(c, MITK_PP_FOR_93, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(93, s), p, o, m) # define MITK_PP_FOR_93_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(94, s) MITK_PP_IIF(c, MITK_PP_FOR_94, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(94, s), p, o, m) # define MITK_PP_FOR_94_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(95, s) MITK_PP_IIF(c, MITK_PP_FOR_95, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(95, s), p, o, m) # define MITK_PP_FOR_95_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(96, s) MITK_PP_IIF(c, MITK_PP_FOR_96, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(96, s), p, o, m) # define MITK_PP_FOR_96_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(97, s) MITK_PP_IIF(c, MITK_PP_FOR_97, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(97, s), p, o, m) # define MITK_PP_FOR_97_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(98, s) MITK_PP_IIF(c, MITK_PP_FOR_98, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(98, s), p, o, m) # define MITK_PP_FOR_98_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(99, s) MITK_PP_IIF(c, MITK_PP_FOR_99, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(99, s), p, o, m) # define MITK_PP_FOR_99_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(100, s) MITK_PP_IIF(c, MITK_PP_FOR_100, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(100, s), p, o, m) # define MITK_PP_FOR_100_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(101, s) MITK_PP_IIF(c, MITK_PP_FOR_101, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(101, s), p, o, m) # define MITK_PP_FOR_101_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(102, s) MITK_PP_IIF(c, MITK_PP_FOR_102, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(102, s), p, o, m) # define MITK_PP_FOR_102_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(103, s) MITK_PP_IIF(c, MITK_PP_FOR_103, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(103, s), p, o, m) # define MITK_PP_FOR_103_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(104, s) MITK_PP_IIF(c, MITK_PP_FOR_104, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(104, s), p, o, m) # define MITK_PP_FOR_104_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(105, s) MITK_PP_IIF(c, MITK_PP_FOR_105, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(105, s), p, o, m) # define MITK_PP_FOR_105_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(106, s) MITK_PP_IIF(c, MITK_PP_FOR_106, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(106, s), p, o, m) # define MITK_PP_FOR_106_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(107, s) MITK_PP_IIF(c, MITK_PP_FOR_107, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(107, s), p, o, m) # define MITK_PP_FOR_107_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(108, s) MITK_PP_IIF(c, MITK_PP_FOR_108, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(108, s), p, o, m) # define MITK_PP_FOR_108_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(109, s) MITK_PP_IIF(c, MITK_PP_FOR_109, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(109, s), p, o, m) # define MITK_PP_FOR_109_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(110, s) MITK_PP_IIF(c, MITK_PP_FOR_110, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(110, s), p, o, m) # define MITK_PP_FOR_110_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(111, s) MITK_PP_IIF(c, MITK_PP_FOR_111, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(111, s), p, o, m) # define MITK_PP_FOR_111_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(112, s) MITK_PP_IIF(c, MITK_PP_FOR_112, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(112, s), p, o, m) # define MITK_PP_FOR_112_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(113, s) MITK_PP_IIF(c, MITK_PP_FOR_113, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(113, s), p, o, m) # define MITK_PP_FOR_113_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(114, s) MITK_PP_IIF(c, MITK_PP_FOR_114, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(114, s), p, o, m) # define MITK_PP_FOR_114_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(115, s) MITK_PP_IIF(c, MITK_PP_FOR_115, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(115, s), p, o, m) # define MITK_PP_FOR_115_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(116, s) MITK_PP_IIF(c, MITK_PP_FOR_116, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(116, s), p, o, m) # define MITK_PP_FOR_116_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(117, s) MITK_PP_IIF(c, MITK_PP_FOR_117, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(117, s), p, o, m) # define MITK_PP_FOR_117_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(118, s) MITK_PP_IIF(c, MITK_PP_FOR_118, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(118, s), p, o, m) # define MITK_PP_FOR_118_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(119, s) MITK_PP_IIF(c, MITK_PP_FOR_119, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(119, s), p, o, m) # define MITK_PP_FOR_119_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(120, s) MITK_PP_IIF(c, MITK_PP_FOR_120, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(120, s), p, o, m) # define MITK_PP_FOR_120_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(121, s) MITK_PP_IIF(c, MITK_PP_FOR_121, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(121, s), p, o, m) # define MITK_PP_FOR_121_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(122, s) MITK_PP_IIF(c, MITK_PP_FOR_122, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(122, s), p, o, m) # define MITK_PP_FOR_122_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(123, s) MITK_PP_IIF(c, MITK_PP_FOR_123, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(123, s), p, o, m) # define MITK_PP_FOR_123_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(124, s) MITK_PP_IIF(c, MITK_PP_FOR_124, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(124, s), p, o, m) # define MITK_PP_FOR_124_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(125, s) MITK_PP_IIF(c, MITK_PP_FOR_125, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(125, s), p, o, m) # define MITK_PP_FOR_125_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(126, s) MITK_PP_IIF(c, MITK_PP_FOR_126, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(126, s), p, o, m) # define MITK_PP_FOR_126_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(127, s) MITK_PP_IIF(c, MITK_PP_FOR_127, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(127, s), p, o, m) # define MITK_PP_FOR_127_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(128, s) MITK_PP_IIF(c, MITK_PP_FOR_128, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(128, s), p, o, m) # define MITK_PP_FOR_128_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(129, s) MITK_PP_IIF(c, MITK_PP_FOR_129, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(129, s), p, o, m) # define MITK_PP_FOR_129_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(130, s) MITK_PP_IIF(c, MITK_PP_FOR_130, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(130, s), p, o, m) # define MITK_PP_FOR_130_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(131, s) MITK_PP_IIF(c, MITK_PP_FOR_131, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(131, s), p, o, m) # define MITK_PP_FOR_131_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(132, s) MITK_PP_IIF(c, MITK_PP_FOR_132, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(132, s), p, o, m) # define MITK_PP_FOR_132_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(133, s) MITK_PP_IIF(c, MITK_PP_FOR_133, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(133, s), p, o, m) # define MITK_PP_FOR_133_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(134, s) MITK_PP_IIF(c, MITK_PP_FOR_134, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(134, s), p, o, m) # define MITK_PP_FOR_134_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(135, s) MITK_PP_IIF(c, MITK_PP_FOR_135, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(135, s), p, o, m) # define MITK_PP_FOR_135_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(136, s) MITK_PP_IIF(c, MITK_PP_FOR_136, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(136, s), p, o, m) # define MITK_PP_FOR_136_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(137, s) MITK_PP_IIF(c, MITK_PP_FOR_137, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(137, s), p, o, m) # define MITK_PP_FOR_137_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(138, s) MITK_PP_IIF(c, MITK_PP_FOR_138, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(138, s), p, o, m) # define MITK_PP_FOR_138_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(139, s) MITK_PP_IIF(c, MITK_PP_FOR_139, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(139, s), p, o, m) # define MITK_PP_FOR_139_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(140, s) MITK_PP_IIF(c, MITK_PP_FOR_140, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(140, s), p, o, m) # define MITK_PP_FOR_140_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(141, s) MITK_PP_IIF(c, MITK_PP_FOR_141, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(141, s), p, o, m) # define MITK_PP_FOR_141_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(142, s) MITK_PP_IIF(c, MITK_PP_FOR_142, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(142, s), p, o, m) # define MITK_PP_FOR_142_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(143, s) MITK_PP_IIF(c, MITK_PP_FOR_143, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(143, s), p, o, m) # define MITK_PP_FOR_143_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(144, s) MITK_PP_IIF(c, MITK_PP_FOR_144, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(144, s), p, o, m) # define MITK_PP_FOR_144_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(145, s) MITK_PP_IIF(c, MITK_PP_FOR_145, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(145, s), p, o, m) # define MITK_PP_FOR_145_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(146, s) MITK_PP_IIF(c, MITK_PP_FOR_146, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(146, s), p, o, m) # define MITK_PP_FOR_146_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(147, s) MITK_PP_IIF(c, MITK_PP_FOR_147, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(147, s), p, o, m) # define MITK_PP_FOR_147_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(148, s) MITK_PP_IIF(c, MITK_PP_FOR_148, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(148, s), p, o, m) # define MITK_PP_FOR_148_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(149, s) MITK_PP_IIF(c, MITK_PP_FOR_149, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(149, s), p, o, m) # define MITK_PP_FOR_149_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(150, s) MITK_PP_IIF(c, MITK_PP_FOR_150, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(150, s), p, o, m) # define MITK_PP_FOR_150_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(151, s) MITK_PP_IIF(c, MITK_PP_FOR_151, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(151, s), p, o, m) # define MITK_PP_FOR_151_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(152, s) MITK_PP_IIF(c, MITK_PP_FOR_152, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(152, s), p, o, m) # define MITK_PP_FOR_152_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(153, s) MITK_PP_IIF(c, MITK_PP_FOR_153, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(153, s), p, o, m) # define MITK_PP_FOR_153_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(154, s) MITK_PP_IIF(c, MITK_PP_FOR_154, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(154, s), p, o, m) # define MITK_PP_FOR_154_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(155, s) MITK_PP_IIF(c, MITK_PP_FOR_155, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(155, s), p, o, m) # define MITK_PP_FOR_155_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(156, s) MITK_PP_IIF(c, MITK_PP_FOR_156, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(156, s), p, o, m) # define MITK_PP_FOR_156_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(157, s) MITK_PP_IIF(c, MITK_PP_FOR_157, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(157, s), p, o, m) # define MITK_PP_FOR_157_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(158, s) MITK_PP_IIF(c, MITK_PP_FOR_158, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(158, s), p, o, m) # define MITK_PP_FOR_158_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(159, s) MITK_PP_IIF(c, MITK_PP_FOR_159, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(159, s), p, o, m) # define MITK_PP_FOR_159_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(160, s) MITK_PP_IIF(c, MITK_PP_FOR_160, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(160, s), p, o, m) # define MITK_PP_FOR_160_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(161, s) MITK_PP_IIF(c, MITK_PP_FOR_161, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(161, s), p, o, m) # define MITK_PP_FOR_161_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(162, s) MITK_PP_IIF(c, MITK_PP_FOR_162, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(162, s), p, o, m) # define MITK_PP_FOR_162_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(163, s) MITK_PP_IIF(c, MITK_PP_FOR_163, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(163, s), p, o, m) # define MITK_PP_FOR_163_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(164, s) MITK_PP_IIF(c, MITK_PP_FOR_164, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(164, s), p, o, m) # define MITK_PP_FOR_164_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(165, s) MITK_PP_IIF(c, MITK_PP_FOR_165, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(165, s), p, o, m) # define MITK_PP_FOR_165_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(166, s) MITK_PP_IIF(c, MITK_PP_FOR_166, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(166, s), p, o, m) # define MITK_PP_FOR_166_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(167, s) MITK_PP_IIF(c, MITK_PP_FOR_167, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(167, s), p, o, m) # define MITK_PP_FOR_167_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(168, s) MITK_PP_IIF(c, MITK_PP_FOR_168, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(168, s), p, o, m) # define MITK_PP_FOR_168_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(169, s) MITK_PP_IIF(c, MITK_PP_FOR_169, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(169, s), p, o, m) # define MITK_PP_FOR_169_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(170, s) MITK_PP_IIF(c, MITK_PP_FOR_170, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(170, s), p, o, m) # define MITK_PP_FOR_170_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(171, s) MITK_PP_IIF(c, MITK_PP_FOR_171, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(171, s), p, o, m) # define MITK_PP_FOR_171_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(172, s) MITK_PP_IIF(c, MITK_PP_FOR_172, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(172, s), p, o, m) # define MITK_PP_FOR_172_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(173, s) MITK_PP_IIF(c, MITK_PP_FOR_173, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(173, s), p, o, m) # define MITK_PP_FOR_173_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(174, s) MITK_PP_IIF(c, MITK_PP_FOR_174, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(174, s), p, o, m) # define MITK_PP_FOR_174_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(175, s) MITK_PP_IIF(c, MITK_PP_FOR_175, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(175, s), p, o, m) # define MITK_PP_FOR_175_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(176, s) MITK_PP_IIF(c, MITK_PP_FOR_176, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(176, s), p, o, m) # define MITK_PP_FOR_176_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(177, s) MITK_PP_IIF(c, MITK_PP_FOR_177, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(177, s), p, o, m) # define MITK_PP_FOR_177_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(178, s) MITK_PP_IIF(c, MITK_PP_FOR_178, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(178, s), p, o, m) # define MITK_PP_FOR_178_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(179, s) MITK_PP_IIF(c, MITK_PP_FOR_179, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(179, s), p, o, m) # define MITK_PP_FOR_179_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(180, s) MITK_PP_IIF(c, MITK_PP_FOR_180, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(180, s), p, o, m) # define MITK_PP_FOR_180_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(181, s) MITK_PP_IIF(c, MITK_PP_FOR_181, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(181, s), p, o, m) # define MITK_PP_FOR_181_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(182, s) MITK_PP_IIF(c, MITK_PP_FOR_182, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(182, s), p, o, m) # define MITK_PP_FOR_182_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(183, s) MITK_PP_IIF(c, MITK_PP_FOR_183, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(183, s), p, o, m) # define MITK_PP_FOR_183_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(184, s) MITK_PP_IIF(c, MITK_PP_FOR_184, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(184, s), p, o, m) # define MITK_PP_FOR_184_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(185, s) MITK_PP_IIF(c, MITK_PP_FOR_185, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(185, s), p, o, m) # define MITK_PP_FOR_185_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(186, s) MITK_PP_IIF(c, MITK_PP_FOR_186, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(186, s), p, o, m) # define MITK_PP_FOR_186_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(187, s) MITK_PP_IIF(c, MITK_PP_FOR_187, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(187, s), p, o, m) # define MITK_PP_FOR_187_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(188, s) MITK_PP_IIF(c, MITK_PP_FOR_188, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(188, s), p, o, m) # define MITK_PP_FOR_188_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(189, s) MITK_PP_IIF(c, MITK_PP_FOR_189, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(189, s), p, o, m) # define MITK_PP_FOR_189_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(190, s) MITK_PP_IIF(c, MITK_PP_FOR_190, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(190, s), p, o, m) # define MITK_PP_FOR_190_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(191, s) MITK_PP_IIF(c, MITK_PP_FOR_191, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(191, s), p, o, m) # define MITK_PP_FOR_191_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(192, s) MITK_PP_IIF(c, MITK_PP_FOR_192, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(192, s), p, o, m) # define MITK_PP_FOR_192_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(193, s) MITK_PP_IIF(c, MITK_PP_FOR_193, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(193, s), p, o, m) # define MITK_PP_FOR_193_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(194, s) MITK_PP_IIF(c, MITK_PP_FOR_194, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(194, s), p, o, m) # define MITK_PP_FOR_194_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(195, s) MITK_PP_IIF(c, MITK_PP_FOR_195, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(195, s), p, o, m) # define MITK_PP_FOR_195_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(196, s) MITK_PP_IIF(c, MITK_PP_FOR_196, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(196, s), p, o, m) # define MITK_PP_FOR_196_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(197, s) MITK_PP_IIF(c, MITK_PP_FOR_197, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(197, s), p, o, m) # define MITK_PP_FOR_197_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(198, s) MITK_PP_IIF(c, MITK_PP_FOR_198, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(198, s), p, o, m) # define MITK_PP_FOR_198_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(199, s) MITK_PP_IIF(c, MITK_PP_FOR_199, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(199, s), p, o, m) # define MITK_PP_FOR_199_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(200, s) MITK_PP_IIF(c, MITK_PP_FOR_200, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(200, s), p, o, m) # define MITK_PP_FOR_200_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(201, s) MITK_PP_IIF(c, MITK_PP_FOR_201, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(201, s), p, o, m) # define MITK_PP_FOR_201_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(202, s) MITK_PP_IIF(c, MITK_PP_FOR_202, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(202, s), p, o, m) # define MITK_PP_FOR_202_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(203, s) MITK_PP_IIF(c, MITK_PP_FOR_203, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(203, s), p, o, m) # define MITK_PP_FOR_203_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(204, s) MITK_PP_IIF(c, MITK_PP_FOR_204, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(204, s), p, o, m) # define MITK_PP_FOR_204_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(205, s) MITK_PP_IIF(c, MITK_PP_FOR_205, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(205, s), p, o, m) # define MITK_PP_FOR_205_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(206, s) MITK_PP_IIF(c, MITK_PP_FOR_206, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(206, s), p, o, m) # define MITK_PP_FOR_206_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(207, s) MITK_PP_IIF(c, MITK_PP_FOR_207, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(207, s), p, o, m) # define MITK_PP_FOR_207_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(208, s) MITK_PP_IIF(c, MITK_PP_FOR_208, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(208, s), p, o, m) # define MITK_PP_FOR_208_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(209, s) MITK_PP_IIF(c, MITK_PP_FOR_209, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(209, s), p, o, m) # define MITK_PP_FOR_209_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(210, s) MITK_PP_IIF(c, MITK_PP_FOR_210, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(210, s), p, o, m) # define MITK_PP_FOR_210_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(211, s) MITK_PP_IIF(c, MITK_PP_FOR_211, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(211, s), p, o, m) # define MITK_PP_FOR_211_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(212, s) MITK_PP_IIF(c, MITK_PP_FOR_212, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(212, s), p, o, m) # define MITK_PP_FOR_212_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(213, s) MITK_PP_IIF(c, MITK_PP_FOR_213, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(213, s), p, o, m) # define MITK_PP_FOR_213_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(214, s) MITK_PP_IIF(c, MITK_PP_FOR_214, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(214, s), p, o, m) # define MITK_PP_FOR_214_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(215, s) MITK_PP_IIF(c, MITK_PP_FOR_215, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(215, s), p, o, m) # define MITK_PP_FOR_215_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(216, s) MITK_PP_IIF(c, MITK_PP_FOR_216, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(216, s), p, o, m) # define MITK_PP_FOR_216_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(217, s) MITK_PP_IIF(c, MITK_PP_FOR_217, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(217, s), p, o, m) # define MITK_PP_FOR_217_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(218, s) MITK_PP_IIF(c, MITK_PP_FOR_218, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(218, s), p, o, m) # define MITK_PP_FOR_218_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(219, s) MITK_PP_IIF(c, MITK_PP_FOR_219, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(219, s), p, o, m) # define MITK_PP_FOR_219_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(220, s) MITK_PP_IIF(c, MITK_PP_FOR_220, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(220, s), p, o, m) # define MITK_PP_FOR_220_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(221, s) MITK_PP_IIF(c, MITK_PP_FOR_221, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(221, s), p, o, m) # define MITK_PP_FOR_221_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(222, s) MITK_PP_IIF(c, MITK_PP_FOR_222, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(222, s), p, o, m) # define MITK_PP_FOR_222_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(223, s) MITK_PP_IIF(c, MITK_PP_FOR_223, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(223, s), p, o, m) # define MITK_PP_FOR_223_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(224, s) MITK_PP_IIF(c, MITK_PP_FOR_224, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(224, s), p, o, m) # define MITK_PP_FOR_224_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(225, s) MITK_PP_IIF(c, MITK_PP_FOR_225, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(225, s), p, o, m) # define MITK_PP_FOR_225_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(226, s) MITK_PP_IIF(c, MITK_PP_FOR_226, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(226, s), p, o, m) # define MITK_PP_FOR_226_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(227, s) MITK_PP_IIF(c, MITK_PP_FOR_227, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(227, s), p, o, m) # define MITK_PP_FOR_227_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(228, s) MITK_PP_IIF(c, MITK_PP_FOR_228, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(228, s), p, o, m) # define MITK_PP_FOR_228_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(229, s) MITK_PP_IIF(c, MITK_PP_FOR_229, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(229, s), p, o, m) # define MITK_PP_FOR_229_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(230, s) MITK_PP_IIF(c, MITK_PP_FOR_230, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(230, s), p, o, m) # define MITK_PP_FOR_230_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(231, s) MITK_PP_IIF(c, MITK_PP_FOR_231, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(231, s), p, o, m) # define MITK_PP_FOR_231_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(232, s) MITK_PP_IIF(c, MITK_PP_FOR_232, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(232, s), p, o, m) # define MITK_PP_FOR_232_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(233, s) MITK_PP_IIF(c, MITK_PP_FOR_233, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(233, s), p, o, m) # define MITK_PP_FOR_233_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(234, s) MITK_PP_IIF(c, MITK_PP_FOR_234, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(234, s), p, o, m) # define MITK_PP_FOR_234_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(235, s) MITK_PP_IIF(c, MITK_PP_FOR_235, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(235, s), p, o, m) # define MITK_PP_FOR_235_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(236, s) MITK_PP_IIF(c, MITK_PP_FOR_236, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(236, s), p, o, m) # define MITK_PP_FOR_236_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(237, s) MITK_PP_IIF(c, MITK_PP_FOR_237, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(237, s), p, o, m) # define MITK_PP_FOR_237_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(238, s) MITK_PP_IIF(c, MITK_PP_FOR_238, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(238, s), p, o, m) # define MITK_PP_FOR_238_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(239, s) MITK_PP_IIF(c, MITK_PP_FOR_239, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(239, s), p, o, m) # define MITK_PP_FOR_239_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(240, s) MITK_PP_IIF(c, MITK_PP_FOR_240, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(240, s), p, o, m) # define MITK_PP_FOR_240_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(241, s) MITK_PP_IIF(c, MITK_PP_FOR_241, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(241, s), p, o, m) # define MITK_PP_FOR_241_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(242, s) MITK_PP_IIF(c, MITK_PP_FOR_242, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(242, s), p, o, m) # define MITK_PP_FOR_242_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(243, s) MITK_PP_IIF(c, MITK_PP_FOR_243, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(243, s), p, o, m) # define MITK_PP_FOR_243_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(244, s) MITK_PP_IIF(c, MITK_PP_FOR_244, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(244, s), p, o, m) # define MITK_PP_FOR_244_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(245, s) MITK_PP_IIF(c, MITK_PP_FOR_245, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(245, s), p, o, m) # define MITK_PP_FOR_245_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(246, s) MITK_PP_IIF(c, MITK_PP_FOR_246, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(246, s), p, o, m) # define MITK_PP_FOR_246_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(247, s) MITK_PP_IIF(c, MITK_PP_FOR_247, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(247, s), p, o, m) # define MITK_PP_FOR_247_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(248, s) MITK_PP_IIF(c, MITK_PP_FOR_248, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(248, s), p, o, m) # define MITK_PP_FOR_248_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(249, s) MITK_PP_IIF(c, MITK_PP_FOR_249, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(249, s), p, o, m) # define MITK_PP_FOR_249_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(250, s) MITK_PP_IIF(c, MITK_PP_FOR_250, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(250, s), p, o, m) # define MITK_PP_FOR_250_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(251, s) MITK_PP_IIF(c, MITK_PP_FOR_251, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(251, s), p, o, m) # define MITK_PP_FOR_251_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(252, s) MITK_PP_IIF(c, MITK_PP_FOR_252, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(252, s), p, o, m) # define MITK_PP_FOR_252_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(253, s) MITK_PP_IIF(c, MITK_PP_FOR_253, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(253, s), p, o, m) # define MITK_PP_FOR_253_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(254, s) MITK_PP_IIF(c, MITK_PP_FOR_254, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(254, s), p, o, m) # define MITK_PP_FOR_254_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(255, s) MITK_PP_IIF(c, MITK_PP_FOR_255, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(255, s), p, o, m) # define MITK_PP_FOR_255_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(256, s) MITK_PP_IIF(c, MITK_PP_FOR_256, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(256, s), p, o, m) # define MITK_PP_FOR_256_C(c, s, p, o, m) MITK_PP_IIF(c, m, MITK_PP_TUPLE_EAT_2)(257, s) MITK_PP_IIF(c, MITK_PP_FOR_257, MITK_PP_TUPLE_EAT_4)(MITK_PP_EXPR_IIF(c, o)(257, s), p, o, m) # # endif diff --git a/Core/Code/Algorithms/mitkPPRepetitionDetailMSVCFor.h b/Core/Code/Algorithms/mitkPPRepetitionDetailMSVCFor.h index 3edbebb55f..7962fc925b 100644 --- a/Core/Code/Algorithms/mitkPPRepetitionDetailMSVCFor.h +++ b/Core/Code/Algorithms/mitkPPRepetitionDetailMSVCFor.h @@ -1,277 +1,292 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_REPETITION_DETAIL_MSVC_FOR_HPP # define MITK_PREPROCESSOR_REPETITION_DETAIL_MSVC_FOR_HPP # # include "mitkPPControlIf.h" # include "mitkPPTupleEat.h" # # define MITK_PP_FOR_1(s, p, o, m) MITK_PP_IF(p(2, s), m, MITK_PP_TUPLE_EAT_2)(2, s) MITK_PP_IF(p(2, s), MITK_PP_FOR_2, MITK_PP_TUPLE_EAT_4)(o(2, s), p, o, m) # define MITK_PP_FOR_2(s, p, o, m) MITK_PP_IF(p(3, s), m, MITK_PP_TUPLE_EAT_2)(3, s) MITK_PP_IF(p(3, s), MITK_PP_FOR_3, MITK_PP_TUPLE_EAT_4)(o(3, s), p, o, m) # define MITK_PP_FOR_3(s, p, o, m) MITK_PP_IF(p(4, s), m, MITK_PP_TUPLE_EAT_2)(4, s) MITK_PP_IF(p(4, s), MITK_PP_FOR_4, MITK_PP_TUPLE_EAT_4)(o(4, s), p, o, m) # define MITK_PP_FOR_4(s, p, o, m) MITK_PP_IF(p(5, s), m, MITK_PP_TUPLE_EAT_2)(5, s) MITK_PP_IF(p(5, s), MITK_PP_FOR_5, MITK_PP_TUPLE_EAT_4)(o(5, s), p, o, m) # define MITK_PP_FOR_5(s, p, o, m) MITK_PP_IF(p(6, s), m, MITK_PP_TUPLE_EAT_2)(6, s) MITK_PP_IF(p(6, s), MITK_PP_FOR_6, MITK_PP_TUPLE_EAT_4)(o(6, s), p, o, m) # define MITK_PP_FOR_6(s, p, o, m) MITK_PP_IF(p(7, s), m, MITK_PP_TUPLE_EAT_2)(7, s) MITK_PP_IF(p(7, s), MITK_PP_FOR_7, MITK_PP_TUPLE_EAT_4)(o(7, s), p, o, m) # define MITK_PP_FOR_7(s, p, o, m) MITK_PP_IF(p(8, s), m, MITK_PP_TUPLE_EAT_2)(8, s) MITK_PP_IF(p(8, s), MITK_PP_FOR_8, MITK_PP_TUPLE_EAT_4)(o(8, s), p, o, m) # define MITK_PP_FOR_8(s, p, o, m) MITK_PP_IF(p(9, s), m, MITK_PP_TUPLE_EAT_2)(9, s) MITK_PP_IF(p(9, s), MITK_PP_FOR_9, MITK_PP_TUPLE_EAT_4)(o(9, s), p, o, m) # define MITK_PP_FOR_9(s, p, o, m) MITK_PP_IF(p(10, s), m, MITK_PP_TUPLE_EAT_2)(10, s) MITK_PP_IF(p(10, s), MITK_PP_FOR_10, MITK_PP_TUPLE_EAT_4)(o(10, s), p, o, m) # define MITK_PP_FOR_10(s, p, o, m) MITK_PP_IF(p(11, s), m, MITK_PP_TUPLE_EAT_2)(11, s) MITK_PP_IF(p(11, s), MITK_PP_FOR_11, MITK_PP_TUPLE_EAT_4)(o(11, s), p, o, m) # define MITK_PP_FOR_11(s, p, o, m) MITK_PP_IF(p(12, s), m, MITK_PP_TUPLE_EAT_2)(12, s) MITK_PP_IF(p(12, s), MITK_PP_FOR_12, MITK_PP_TUPLE_EAT_4)(o(12, s), p, o, m) # define MITK_PP_FOR_12(s, p, o, m) MITK_PP_IF(p(13, s), m, MITK_PP_TUPLE_EAT_2)(13, s) MITK_PP_IF(p(13, s), MITK_PP_FOR_13, MITK_PP_TUPLE_EAT_4)(o(13, s), p, o, m) # define MITK_PP_FOR_13(s, p, o, m) MITK_PP_IF(p(14, s), m, MITK_PP_TUPLE_EAT_2)(14, s) MITK_PP_IF(p(14, s), MITK_PP_FOR_14, MITK_PP_TUPLE_EAT_4)(o(14, s), p, o, m) # define MITK_PP_FOR_14(s, p, o, m) MITK_PP_IF(p(15, s), m, MITK_PP_TUPLE_EAT_2)(15, s) MITK_PP_IF(p(15, s), MITK_PP_FOR_15, MITK_PP_TUPLE_EAT_4)(o(15, s), p, o, m) # define MITK_PP_FOR_15(s, p, o, m) MITK_PP_IF(p(16, s), m, MITK_PP_TUPLE_EAT_2)(16, s) MITK_PP_IF(p(16, s), MITK_PP_FOR_16, MITK_PP_TUPLE_EAT_4)(o(16, s), p, o, m) # define MITK_PP_FOR_16(s, p, o, m) MITK_PP_IF(p(17, s), m, MITK_PP_TUPLE_EAT_2)(17, s) MITK_PP_IF(p(17, s), MITK_PP_FOR_17, MITK_PP_TUPLE_EAT_4)(o(17, s), p, o, m) # define MITK_PP_FOR_17(s, p, o, m) MITK_PP_IF(p(18, s), m, MITK_PP_TUPLE_EAT_2)(18, s) MITK_PP_IF(p(18, s), MITK_PP_FOR_18, MITK_PP_TUPLE_EAT_4)(o(18, s), p, o, m) # define MITK_PP_FOR_18(s, p, o, m) MITK_PP_IF(p(19, s), m, MITK_PP_TUPLE_EAT_2)(19, s) MITK_PP_IF(p(19, s), MITK_PP_FOR_19, MITK_PP_TUPLE_EAT_4)(o(19, s), p, o, m) # define MITK_PP_FOR_19(s, p, o, m) MITK_PP_IF(p(20, s), m, MITK_PP_TUPLE_EAT_2)(20, s) MITK_PP_IF(p(20, s), MITK_PP_FOR_20, MITK_PP_TUPLE_EAT_4)(o(20, s), p, o, m) # define MITK_PP_FOR_20(s, p, o, m) MITK_PP_IF(p(21, s), m, MITK_PP_TUPLE_EAT_2)(21, s) MITK_PP_IF(p(21, s), MITK_PP_FOR_21, MITK_PP_TUPLE_EAT_4)(o(21, s), p, o, m) # define MITK_PP_FOR_21(s, p, o, m) MITK_PP_IF(p(22, s), m, MITK_PP_TUPLE_EAT_2)(22, s) MITK_PP_IF(p(22, s), MITK_PP_FOR_22, MITK_PP_TUPLE_EAT_4)(o(22, s), p, o, m) # define MITK_PP_FOR_22(s, p, o, m) MITK_PP_IF(p(23, s), m, MITK_PP_TUPLE_EAT_2)(23, s) MITK_PP_IF(p(23, s), MITK_PP_FOR_23, MITK_PP_TUPLE_EAT_4)(o(23, s), p, o, m) # define MITK_PP_FOR_23(s, p, o, m) MITK_PP_IF(p(24, s), m, MITK_PP_TUPLE_EAT_2)(24, s) MITK_PP_IF(p(24, s), MITK_PP_FOR_24, MITK_PP_TUPLE_EAT_4)(o(24, s), p, o, m) # define MITK_PP_FOR_24(s, p, o, m) MITK_PP_IF(p(25, s), m, MITK_PP_TUPLE_EAT_2)(25, s) MITK_PP_IF(p(25, s), MITK_PP_FOR_25, MITK_PP_TUPLE_EAT_4)(o(25, s), p, o, m) # define MITK_PP_FOR_25(s, p, o, m) MITK_PP_IF(p(26, s), m, MITK_PP_TUPLE_EAT_2)(26, s) MITK_PP_IF(p(26, s), MITK_PP_FOR_26, MITK_PP_TUPLE_EAT_4)(o(26, s), p, o, m) # define MITK_PP_FOR_26(s, p, o, m) MITK_PP_IF(p(27, s), m, MITK_PP_TUPLE_EAT_2)(27, s) MITK_PP_IF(p(27, s), MITK_PP_FOR_27, MITK_PP_TUPLE_EAT_4)(o(27, s), p, o, m) # define MITK_PP_FOR_27(s, p, o, m) MITK_PP_IF(p(28, s), m, MITK_PP_TUPLE_EAT_2)(28, s) MITK_PP_IF(p(28, s), MITK_PP_FOR_28, MITK_PP_TUPLE_EAT_4)(o(28, s), p, o, m) # define MITK_PP_FOR_28(s, p, o, m) MITK_PP_IF(p(29, s), m, MITK_PP_TUPLE_EAT_2)(29, s) MITK_PP_IF(p(29, s), MITK_PP_FOR_29, MITK_PP_TUPLE_EAT_4)(o(29, s), p, o, m) # define MITK_PP_FOR_29(s, p, o, m) MITK_PP_IF(p(30, s), m, MITK_PP_TUPLE_EAT_2)(30, s) MITK_PP_IF(p(30, s), MITK_PP_FOR_30, MITK_PP_TUPLE_EAT_4)(o(30, s), p, o, m) # define MITK_PP_FOR_30(s, p, o, m) MITK_PP_IF(p(31, s), m, MITK_PP_TUPLE_EAT_2)(31, s) MITK_PP_IF(p(31, s), MITK_PP_FOR_31, MITK_PP_TUPLE_EAT_4)(o(31, s), p, o, m) # define MITK_PP_FOR_31(s, p, o, m) MITK_PP_IF(p(32, s), m, MITK_PP_TUPLE_EAT_2)(32, s) MITK_PP_IF(p(32, s), MITK_PP_FOR_32, MITK_PP_TUPLE_EAT_4)(o(32, s), p, o, m) # define MITK_PP_FOR_32(s, p, o, m) MITK_PP_IF(p(33, s), m, MITK_PP_TUPLE_EAT_2)(33, s) MITK_PP_IF(p(33, s), MITK_PP_FOR_33, MITK_PP_TUPLE_EAT_4)(o(33, s), p, o, m) # define MITK_PP_FOR_33(s, p, o, m) MITK_PP_IF(p(34, s), m, MITK_PP_TUPLE_EAT_2)(34, s) MITK_PP_IF(p(34, s), MITK_PP_FOR_34, MITK_PP_TUPLE_EAT_4)(o(34, s), p, o, m) # define MITK_PP_FOR_34(s, p, o, m) MITK_PP_IF(p(35, s), m, MITK_PP_TUPLE_EAT_2)(35, s) MITK_PP_IF(p(35, s), MITK_PP_FOR_35, MITK_PP_TUPLE_EAT_4)(o(35, s), p, o, m) # define MITK_PP_FOR_35(s, p, o, m) MITK_PP_IF(p(36, s), m, MITK_PP_TUPLE_EAT_2)(36, s) MITK_PP_IF(p(36, s), MITK_PP_FOR_36, MITK_PP_TUPLE_EAT_4)(o(36, s), p, o, m) # define MITK_PP_FOR_36(s, p, o, m) MITK_PP_IF(p(37, s), m, MITK_PP_TUPLE_EAT_2)(37, s) MITK_PP_IF(p(37, s), MITK_PP_FOR_37, MITK_PP_TUPLE_EAT_4)(o(37, s), p, o, m) # define MITK_PP_FOR_37(s, p, o, m) MITK_PP_IF(p(38, s), m, MITK_PP_TUPLE_EAT_2)(38, s) MITK_PP_IF(p(38, s), MITK_PP_FOR_38, MITK_PP_TUPLE_EAT_4)(o(38, s), p, o, m) # define MITK_PP_FOR_38(s, p, o, m) MITK_PP_IF(p(39, s), m, MITK_PP_TUPLE_EAT_2)(39, s) MITK_PP_IF(p(39, s), MITK_PP_FOR_39, MITK_PP_TUPLE_EAT_4)(o(39, s), p, o, m) # define MITK_PP_FOR_39(s, p, o, m) MITK_PP_IF(p(40, s), m, MITK_PP_TUPLE_EAT_2)(40, s) MITK_PP_IF(p(40, s), MITK_PP_FOR_40, MITK_PP_TUPLE_EAT_4)(o(40, s), p, o, m) # define MITK_PP_FOR_40(s, p, o, m) MITK_PP_IF(p(41, s), m, MITK_PP_TUPLE_EAT_2)(41, s) MITK_PP_IF(p(41, s), MITK_PP_FOR_41, MITK_PP_TUPLE_EAT_4)(o(41, s), p, o, m) # define MITK_PP_FOR_41(s, p, o, m) MITK_PP_IF(p(42, s), m, MITK_PP_TUPLE_EAT_2)(42, s) MITK_PP_IF(p(42, s), MITK_PP_FOR_42, MITK_PP_TUPLE_EAT_4)(o(42, s), p, o, m) # define MITK_PP_FOR_42(s, p, o, m) MITK_PP_IF(p(43, s), m, MITK_PP_TUPLE_EAT_2)(43, s) MITK_PP_IF(p(43, s), MITK_PP_FOR_43, MITK_PP_TUPLE_EAT_4)(o(43, s), p, o, m) # define MITK_PP_FOR_43(s, p, o, m) MITK_PP_IF(p(44, s), m, MITK_PP_TUPLE_EAT_2)(44, s) MITK_PP_IF(p(44, s), MITK_PP_FOR_44, MITK_PP_TUPLE_EAT_4)(o(44, s), p, o, m) # define MITK_PP_FOR_44(s, p, o, m) MITK_PP_IF(p(45, s), m, MITK_PP_TUPLE_EAT_2)(45, s) MITK_PP_IF(p(45, s), MITK_PP_FOR_45, MITK_PP_TUPLE_EAT_4)(o(45, s), p, o, m) # define MITK_PP_FOR_45(s, p, o, m) MITK_PP_IF(p(46, s), m, MITK_PP_TUPLE_EAT_2)(46, s) MITK_PP_IF(p(46, s), MITK_PP_FOR_46, MITK_PP_TUPLE_EAT_4)(o(46, s), p, o, m) # define MITK_PP_FOR_46(s, p, o, m) MITK_PP_IF(p(47, s), m, MITK_PP_TUPLE_EAT_2)(47, s) MITK_PP_IF(p(47, s), MITK_PP_FOR_47, MITK_PP_TUPLE_EAT_4)(o(47, s), p, o, m) # define MITK_PP_FOR_47(s, p, o, m) MITK_PP_IF(p(48, s), m, MITK_PP_TUPLE_EAT_2)(48, s) MITK_PP_IF(p(48, s), MITK_PP_FOR_48, MITK_PP_TUPLE_EAT_4)(o(48, s), p, o, m) # define MITK_PP_FOR_48(s, p, o, m) MITK_PP_IF(p(49, s), m, MITK_PP_TUPLE_EAT_2)(49, s) MITK_PP_IF(p(49, s), MITK_PP_FOR_49, MITK_PP_TUPLE_EAT_4)(o(49, s), p, o, m) # define MITK_PP_FOR_49(s, p, o, m) MITK_PP_IF(p(50, s), m, MITK_PP_TUPLE_EAT_2)(50, s) MITK_PP_IF(p(50, s), MITK_PP_FOR_50, MITK_PP_TUPLE_EAT_4)(o(50, s), p, o, m) # define MITK_PP_FOR_50(s, p, o, m) MITK_PP_IF(p(51, s), m, MITK_PP_TUPLE_EAT_2)(51, s) MITK_PP_IF(p(51, s), MITK_PP_FOR_51, MITK_PP_TUPLE_EAT_4)(o(51, s), p, o, m) # define MITK_PP_FOR_51(s, p, o, m) MITK_PP_IF(p(52, s), m, MITK_PP_TUPLE_EAT_2)(52, s) MITK_PP_IF(p(52, s), MITK_PP_FOR_52, MITK_PP_TUPLE_EAT_4)(o(52, s), p, o, m) # define MITK_PP_FOR_52(s, p, o, m) MITK_PP_IF(p(53, s), m, MITK_PP_TUPLE_EAT_2)(53, s) MITK_PP_IF(p(53, s), MITK_PP_FOR_53, MITK_PP_TUPLE_EAT_4)(o(53, s), p, o, m) # define MITK_PP_FOR_53(s, p, o, m) MITK_PP_IF(p(54, s), m, MITK_PP_TUPLE_EAT_2)(54, s) MITK_PP_IF(p(54, s), MITK_PP_FOR_54, MITK_PP_TUPLE_EAT_4)(o(54, s), p, o, m) # define MITK_PP_FOR_54(s, p, o, m) MITK_PP_IF(p(55, s), m, MITK_PP_TUPLE_EAT_2)(55, s) MITK_PP_IF(p(55, s), MITK_PP_FOR_55, MITK_PP_TUPLE_EAT_4)(o(55, s), p, o, m) # define MITK_PP_FOR_55(s, p, o, m) MITK_PP_IF(p(56, s), m, MITK_PP_TUPLE_EAT_2)(56, s) MITK_PP_IF(p(56, s), MITK_PP_FOR_56, MITK_PP_TUPLE_EAT_4)(o(56, s), p, o, m) # define MITK_PP_FOR_56(s, p, o, m) MITK_PP_IF(p(57, s), m, MITK_PP_TUPLE_EAT_2)(57, s) MITK_PP_IF(p(57, s), MITK_PP_FOR_57, MITK_PP_TUPLE_EAT_4)(o(57, s), p, o, m) # define MITK_PP_FOR_57(s, p, o, m) MITK_PP_IF(p(58, s), m, MITK_PP_TUPLE_EAT_2)(58, s) MITK_PP_IF(p(58, s), MITK_PP_FOR_58, MITK_PP_TUPLE_EAT_4)(o(58, s), p, o, m) # define MITK_PP_FOR_58(s, p, o, m) MITK_PP_IF(p(59, s), m, MITK_PP_TUPLE_EAT_2)(59, s) MITK_PP_IF(p(59, s), MITK_PP_FOR_59, MITK_PP_TUPLE_EAT_4)(o(59, s), p, o, m) # define MITK_PP_FOR_59(s, p, o, m) MITK_PP_IF(p(60, s), m, MITK_PP_TUPLE_EAT_2)(60, s) MITK_PP_IF(p(60, s), MITK_PP_FOR_60, MITK_PP_TUPLE_EAT_4)(o(60, s), p, o, m) # define MITK_PP_FOR_60(s, p, o, m) MITK_PP_IF(p(61, s), m, MITK_PP_TUPLE_EAT_2)(61, s) MITK_PP_IF(p(61, s), MITK_PP_FOR_61, MITK_PP_TUPLE_EAT_4)(o(61, s), p, o, m) # define MITK_PP_FOR_61(s, p, o, m) MITK_PP_IF(p(62, s), m, MITK_PP_TUPLE_EAT_2)(62, s) MITK_PP_IF(p(62, s), MITK_PP_FOR_62, MITK_PP_TUPLE_EAT_4)(o(62, s), p, o, m) # define MITK_PP_FOR_62(s, p, o, m) MITK_PP_IF(p(63, s), m, MITK_PP_TUPLE_EAT_2)(63, s) MITK_PP_IF(p(63, s), MITK_PP_FOR_63, MITK_PP_TUPLE_EAT_4)(o(63, s), p, o, m) # define MITK_PP_FOR_63(s, p, o, m) MITK_PP_IF(p(64, s), m, MITK_PP_TUPLE_EAT_2)(64, s) MITK_PP_IF(p(64, s), MITK_PP_FOR_64, MITK_PP_TUPLE_EAT_4)(o(64, s), p, o, m) # define MITK_PP_FOR_64(s, p, o, m) MITK_PP_IF(p(65, s), m, MITK_PP_TUPLE_EAT_2)(65, s) MITK_PP_IF(p(65, s), MITK_PP_FOR_65, MITK_PP_TUPLE_EAT_4)(o(65, s), p, o, m) # define MITK_PP_FOR_65(s, p, o, m) MITK_PP_IF(p(66, s), m, MITK_PP_TUPLE_EAT_2)(66, s) MITK_PP_IF(p(66, s), MITK_PP_FOR_66, MITK_PP_TUPLE_EAT_4)(o(66, s), p, o, m) # define MITK_PP_FOR_66(s, p, o, m) MITK_PP_IF(p(67, s), m, MITK_PP_TUPLE_EAT_2)(67, s) MITK_PP_IF(p(67, s), MITK_PP_FOR_67, MITK_PP_TUPLE_EAT_4)(o(67, s), p, o, m) # define MITK_PP_FOR_67(s, p, o, m) MITK_PP_IF(p(68, s), m, MITK_PP_TUPLE_EAT_2)(68, s) MITK_PP_IF(p(68, s), MITK_PP_FOR_68, MITK_PP_TUPLE_EAT_4)(o(68, s), p, o, m) # define MITK_PP_FOR_68(s, p, o, m) MITK_PP_IF(p(69, s), m, MITK_PP_TUPLE_EAT_2)(69, s) MITK_PP_IF(p(69, s), MITK_PP_FOR_69, MITK_PP_TUPLE_EAT_4)(o(69, s), p, o, m) # define MITK_PP_FOR_69(s, p, o, m) MITK_PP_IF(p(70, s), m, MITK_PP_TUPLE_EAT_2)(70, s) MITK_PP_IF(p(70, s), MITK_PP_FOR_70, MITK_PP_TUPLE_EAT_4)(o(70, s), p, o, m) # define MITK_PP_FOR_70(s, p, o, m) MITK_PP_IF(p(71, s), m, MITK_PP_TUPLE_EAT_2)(71, s) MITK_PP_IF(p(71, s), MITK_PP_FOR_71, MITK_PP_TUPLE_EAT_4)(o(71, s), p, o, m) # define MITK_PP_FOR_71(s, p, o, m) MITK_PP_IF(p(72, s), m, MITK_PP_TUPLE_EAT_2)(72, s) MITK_PP_IF(p(72, s), MITK_PP_FOR_72, MITK_PP_TUPLE_EAT_4)(o(72, s), p, o, m) # define MITK_PP_FOR_72(s, p, o, m) MITK_PP_IF(p(73, s), m, MITK_PP_TUPLE_EAT_2)(73, s) MITK_PP_IF(p(73, s), MITK_PP_FOR_73, MITK_PP_TUPLE_EAT_4)(o(73, s), p, o, m) # define MITK_PP_FOR_73(s, p, o, m) MITK_PP_IF(p(74, s), m, MITK_PP_TUPLE_EAT_2)(74, s) MITK_PP_IF(p(74, s), MITK_PP_FOR_74, MITK_PP_TUPLE_EAT_4)(o(74, s), p, o, m) # define MITK_PP_FOR_74(s, p, o, m) MITK_PP_IF(p(75, s), m, MITK_PP_TUPLE_EAT_2)(75, s) MITK_PP_IF(p(75, s), MITK_PP_FOR_75, MITK_PP_TUPLE_EAT_4)(o(75, s), p, o, m) # define MITK_PP_FOR_75(s, p, o, m) MITK_PP_IF(p(76, s), m, MITK_PP_TUPLE_EAT_2)(76, s) MITK_PP_IF(p(76, s), MITK_PP_FOR_76, MITK_PP_TUPLE_EAT_4)(o(76, s), p, o, m) # define MITK_PP_FOR_76(s, p, o, m) MITK_PP_IF(p(77, s), m, MITK_PP_TUPLE_EAT_2)(77, s) MITK_PP_IF(p(77, s), MITK_PP_FOR_77, MITK_PP_TUPLE_EAT_4)(o(77, s), p, o, m) # define MITK_PP_FOR_77(s, p, o, m) MITK_PP_IF(p(78, s), m, MITK_PP_TUPLE_EAT_2)(78, s) MITK_PP_IF(p(78, s), MITK_PP_FOR_78, MITK_PP_TUPLE_EAT_4)(o(78, s), p, o, m) # define MITK_PP_FOR_78(s, p, o, m) MITK_PP_IF(p(79, s), m, MITK_PP_TUPLE_EAT_2)(79, s) MITK_PP_IF(p(79, s), MITK_PP_FOR_79, MITK_PP_TUPLE_EAT_4)(o(79, s), p, o, m) # define MITK_PP_FOR_79(s, p, o, m) MITK_PP_IF(p(80, s), m, MITK_PP_TUPLE_EAT_2)(80, s) MITK_PP_IF(p(80, s), MITK_PP_FOR_80, MITK_PP_TUPLE_EAT_4)(o(80, s), p, o, m) # define MITK_PP_FOR_80(s, p, o, m) MITK_PP_IF(p(81, s), m, MITK_PP_TUPLE_EAT_2)(81, s) MITK_PP_IF(p(81, s), MITK_PP_FOR_81, MITK_PP_TUPLE_EAT_4)(o(81, s), p, o, m) # define MITK_PP_FOR_81(s, p, o, m) MITK_PP_IF(p(82, s), m, MITK_PP_TUPLE_EAT_2)(82, s) MITK_PP_IF(p(82, s), MITK_PP_FOR_82, MITK_PP_TUPLE_EAT_4)(o(82, s), p, o, m) # define MITK_PP_FOR_82(s, p, o, m) MITK_PP_IF(p(83, s), m, MITK_PP_TUPLE_EAT_2)(83, s) MITK_PP_IF(p(83, s), MITK_PP_FOR_83, MITK_PP_TUPLE_EAT_4)(o(83, s), p, o, m) # define MITK_PP_FOR_83(s, p, o, m) MITK_PP_IF(p(84, s), m, MITK_PP_TUPLE_EAT_2)(84, s) MITK_PP_IF(p(84, s), MITK_PP_FOR_84, MITK_PP_TUPLE_EAT_4)(o(84, s), p, o, m) # define MITK_PP_FOR_84(s, p, o, m) MITK_PP_IF(p(85, s), m, MITK_PP_TUPLE_EAT_2)(85, s) MITK_PP_IF(p(85, s), MITK_PP_FOR_85, MITK_PP_TUPLE_EAT_4)(o(85, s), p, o, m) # define MITK_PP_FOR_85(s, p, o, m) MITK_PP_IF(p(86, s), m, MITK_PP_TUPLE_EAT_2)(86, s) MITK_PP_IF(p(86, s), MITK_PP_FOR_86, MITK_PP_TUPLE_EAT_4)(o(86, s), p, o, m) # define MITK_PP_FOR_86(s, p, o, m) MITK_PP_IF(p(87, s), m, MITK_PP_TUPLE_EAT_2)(87, s) MITK_PP_IF(p(87, s), MITK_PP_FOR_87, MITK_PP_TUPLE_EAT_4)(o(87, s), p, o, m) # define MITK_PP_FOR_87(s, p, o, m) MITK_PP_IF(p(88, s), m, MITK_PP_TUPLE_EAT_2)(88, s) MITK_PP_IF(p(88, s), MITK_PP_FOR_88, MITK_PP_TUPLE_EAT_4)(o(88, s), p, o, m) # define MITK_PP_FOR_88(s, p, o, m) MITK_PP_IF(p(89, s), m, MITK_PP_TUPLE_EAT_2)(89, s) MITK_PP_IF(p(89, s), MITK_PP_FOR_89, MITK_PP_TUPLE_EAT_4)(o(89, s), p, o, m) # define MITK_PP_FOR_89(s, p, o, m) MITK_PP_IF(p(90, s), m, MITK_PP_TUPLE_EAT_2)(90, s) MITK_PP_IF(p(90, s), MITK_PP_FOR_90, MITK_PP_TUPLE_EAT_4)(o(90, s), p, o, m) # define MITK_PP_FOR_90(s, p, o, m) MITK_PP_IF(p(91, s), m, MITK_PP_TUPLE_EAT_2)(91, s) MITK_PP_IF(p(91, s), MITK_PP_FOR_91, MITK_PP_TUPLE_EAT_4)(o(91, s), p, o, m) # define MITK_PP_FOR_91(s, p, o, m) MITK_PP_IF(p(92, s), m, MITK_PP_TUPLE_EAT_2)(92, s) MITK_PP_IF(p(92, s), MITK_PP_FOR_92, MITK_PP_TUPLE_EAT_4)(o(92, s), p, o, m) # define MITK_PP_FOR_92(s, p, o, m) MITK_PP_IF(p(93, s), m, MITK_PP_TUPLE_EAT_2)(93, s) MITK_PP_IF(p(93, s), MITK_PP_FOR_93, MITK_PP_TUPLE_EAT_4)(o(93, s), p, o, m) # define MITK_PP_FOR_93(s, p, o, m) MITK_PP_IF(p(94, s), m, MITK_PP_TUPLE_EAT_2)(94, s) MITK_PP_IF(p(94, s), MITK_PP_FOR_94, MITK_PP_TUPLE_EAT_4)(o(94, s), p, o, m) # define MITK_PP_FOR_94(s, p, o, m) MITK_PP_IF(p(95, s), m, MITK_PP_TUPLE_EAT_2)(95, s) MITK_PP_IF(p(95, s), MITK_PP_FOR_95, MITK_PP_TUPLE_EAT_4)(o(95, s), p, o, m) # define MITK_PP_FOR_95(s, p, o, m) MITK_PP_IF(p(96, s), m, MITK_PP_TUPLE_EAT_2)(96, s) MITK_PP_IF(p(96, s), MITK_PP_FOR_96, MITK_PP_TUPLE_EAT_4)(o(96, s), p, o, m) # define MITK_PP_FOR_96(s, p, o, m) MITK_PP_IF(p(97, s), m, MITK_PP_TUPLE_EAT_2)(97, s) MITK_PP_IF(p(97, s), MITK_PP_FOR_97, MITK_PP_TUPLE_EAT_4)(o(97, s), p, o, m) # define MITK_PP_FOR_97(s, p, o, m) MITK_PP_IF(p(98, s), m, MITK_PP_TUPLE_EAT_2)(98, s) MITK_PP_IF(p(98, s), MITK_PP_FOR_98, MITK_PP_TUPLE_EAT_4)(o(98, s), p, o, m) # define MITK_PP_FOR_98(s, p, o, m) MITK_PP_IF(p(99, s), m, MITK_PP_TUPLE_EAT_2)(99, s) MITK_PP_IF(p(99, s), MITK_PP_FOR_99, MITK_PP_TUPLE_EAT_4)(o(99, s), p, o, m) # define MITK_PP_FOR_99(s, p, o, m) MITK_PP_IF(p(100, s), m, MITK_PP_TUPLE_EAT_2)(100, s) MITK_PP_IF(p(100, s), MITK_PP_FOR_100, MITK_PP_TUPLE_EAT_4)(o(100, s), p, o, m) # define MITK_PP_FOR_100(s, p, o, m) MITK_PP_IF(p(101, s), m, MITK_PP_TUPLE_EAT_2)(101, s) MITK_PP_IF(p(101, s), MITK_PP_FOR_101, MITK_PP_TUPLE_EAT_4)(o(101, s), p, o, m) # define MITK_PP_FOR_101(s, p, o, m) MITK_PP_IF(p(102, s), m, MITK_PP_TUPLE_EAT_2)(102, s) MITK_PP_IF(p(102, s), MITK_PP_FOR_102, MITK_PP_TUPLE_EAT_4)(o(102, s), p, o, m) # define MITK_PP_FOR_102(s, p, o, m) MITK_PP_IF(p(103, s), m, MITK_PP_TUPLE_EAT_2)(103, s) MITK_PP_IF(p(103, s), MITK_PP_FOR_103, MITK_PP_TUPLE_EAT_4)(o(103, s), p, o, m) # define MITK_PP_FOR_103(s, p, o, m) MITK_PP_IF(p(104, s), m, MITK_PP_TUPLE_EAT_2)(104, s) MITK_PP_IF(p(104, s), MITK_PP_FOR_104, MITK_PP_TUPLE_EAT_4)(o(104, s), p, o, m) # define MITK_PP_FOR_104(s, p, o, m) MITK_PP_IF(p(105, s), m, MITK_PP_TUPLE_EAT_2)(105, s) MITK_PP_IF(p(105, s), MITK_PP_FOR_105, MITK_PP_TUPLE_EAT_4)(o(105, s), p, o, m) # define MITK_PP_FOR_105(s, p, o, m) MITK_PP_IF(p(106, s), m, MITK_PP_TUPLE_EAT_2)(106, s) MITK_PP_IF(p(106, s), MITK_PP_FOR_106, MITK_PP_TUPLE_EAT_4)(o(106, s), p, o, m) # define MITK_PP_FOR_106(s, p, o, m) MITK_PP_IF(p(107, s), m, MITK_PP_TUPLE_EAT_2)(107, s) MITK_PP_IF(p(107, s), MITK_PP_FOR_107, MITK_PP_TUPLE_EAT_4)(o(107, s), p, o, m) # define MITK_PP_FOR_107(s, p, o, m) MITK_PP_IF(p(108, s), m, MITK_PP_TUPLE_EAT_2)(108, s) MITK_PP_IF(p(108, s), MITK_PP_FOR_108, MITK_PP_TUPLE_EAT_4)(o(108, s), p, o, m) # define MITK_PP_FOR_108(s, p, o, m) MITK_PP_IF(p(109, s), m, MITK_PP_TUPLE_EAT_2)(109, s) MITK_PP_IF(p(109, s), MITK_PP_FOR_109, MITK_PP_TUPLE_EAT_4)(o(109, s), p, o, m) # define MITK_PP_FOR_109(s, p, o, m) MITK_PP_IF(p(110, s), m, MITK_PP_TUPLE_EAT_2)(110, s) MITK_PP_IF(p(110, s), MITK_PP_FOR_110, MITK_PP_TUPLE_EAT_4)(o(110, s), p, o, m) # define MITK_PP_FOR_110(s, p, o, m) MITK_PP_IF(p(111, s), m, MITK_PP_TUPLE_EAT_2)(111, s) MITK_PP_IF(p(111, s), MITK_PP_FOR_111, MITK_PP_TUPLE_EAT_4)(o(111, s), p, o, m) # define MITK_PP_FOR_111(s, p, o, m) MITK_PP_IF(p(112, s), m, MITK_PP_TUPLE_EAT_2)(112, s) MITK_PP_IF(p(112, s), MITK_PP_FOR_112, MITK_PP_TUPLE_EAT_4)(o(112, s), p, o, m) # define MITK_PP_FOR_112(s, p, o, m) MITK_PP_IF(p(113, s), m, MITK_PP_TUPLE_EAT_2)(113, s) MITK_PP_IF(p(113, s), MITK_PP_FOR_113, MITK_PP_TUPLE_EAT_4)(o(113, s), p, o, m) # define MITK_PP_FOR_113(s, p, o, m) MITK_PP_IF(p(114, s), m, MITK_PP_TUPLE_EAT_2)(114, s) MITK_PP_IF(p(114, s), MITK_PP_FOR_114, MITK_PP_TUPLE_EAT_4)(o(114, s), p, o, m) # define MITK_PP_FOR_114(s, p, o, m) MITK_PP_IF(p(115, s), m, MITK_PP_TUPLE_EAT_2)(115, s) MITK_PP_IF(p(115, s), MITK_PP_FOR_115, MITK_PP_TUPLE_EAT_4)(o(115, s), p, o, m) # define MITK_PP_FOR_115(s, p, o, m) MITK_PP_IF(p(116, s), m, MITK_PP_TUPLE_EAT_2)(116, s) MITK_PP_IF(p(116, s), MITK_PP_FOR_116, MITK_PP_TUPLE_EAT_4)(o(116, s), p, o, m) # define MITK_PP_FOR_116(s, p, o, m) MITK_PP_IF(p(117, s), m, MITK_PP_TUPLE_EAT_2)(117, s) MITK_PP_IF(p(117, s), MITK_PP_FOR_117, MITK_PP_TUPLE_EAT_4)(o(117, s), p, o, m) # define MITK_PP_FOR_117(s, p, o, m) MITK_PP_IF(p(118, s), m, MITK_PP_TUPLE_EAT_2)(118, s) MITK_PP_IF(p(118, s), MITK_PP_FOR_118, MITK_PP_TUPLE_EAT_4)(o(118, s), p, o, m) # define MITK_PP_FOR_118(s, p, o, m) MITK_PP_IF(p(119, s), m, MITK_PP_TUPLE_EAT_2)(119, s) MITK_PP_IF(p(119, s), MITK_PP_FOR_119, MITK_PP_TUPLE_EAT_4)(o(119, s), p, o, m) # define MITK_PP_FOR_119(s, p, o, m) MITK_PP_IF(p(120, s), m, MITK_PP_TUPLE_EAT_2)(120, s) MITK_PP_IF(p(120, s), MITK_PP_FOR_120, MITK_PP_TUPLE_EAT_4)(o(120, s), p, o, m) # define MITK_PP_FOR_120(s, p, o, m) MITK_PP_IF(p(121, s), m, MITK_PP_TUPLE_EAT_2)(121, s) MITK_PP_IF(p(121, s), MITK_PP_FOR_121, MITK_PP_TUPLE_EAT_4)(o(121, s), p, o, m) # define MITK_PP_FOR_121(s, p, o, m) MITK_PP_IF(p(122, s), m, MITK_PP_TUPLE_EAT_2)(122, s) MITK_PP_IF(p(122, s), MITK_PP_FOR_122, MITK_PP_TUPLE_EAT_4)(o(122, s), p, o, m) # define MITK_PP_FOR_122(s, p, o, m) MITK_PP_IF(p(123, s), m, MITK_PP_TUPLE_EAT_2)(123, s) MITK_PP_IF(p(123, s), MITK_PP_FOR_123, MITK_PP_TUPLE_EAT_4)(o(123, s), p, o, m) # define MITK_PP_FOR_123(s, p, o, m) MITK_PP_IF(p(124, s), m, MITK_PP_TUPLE_EAT_2)(124, s) MITK_PP_IF(p(124, s), MITK_PP_FOR_124, MITK_PP_TUPLE_EAT_4)(o(124, s), p, o, m) # define MITK_PP_FOR_124(s, p, o, m) MITK_PP_IF(p(125, s), m, MITK_PP_TUPLE_EAT_2)(125, s) MITK_PP_IF(p(125, s), MITK_PP_FOR_125, MITK_PP_TUPLE_EAT_4)(o(125, s), p, o, m) # define MITK_PP_FOR_125(s, p, o, m) MITK_PP_IF(p(126, s), m, MITK_PP_TUPLE_EAT_2)(126, s) MITK_PP_IF(p(126, s), MITK_PP_FOR_126, MITK_PP_TUPLE_EAT_4)(o(126, s), p, o, m) # define MITK_PP_FOR_126(s, p, o, m) MITK_PP_IF(p(127, s), m, MITK_PP_TUPLE_EAT_2)(127, s) MITK_PP_IF(p(127, s), MITK_PP_FOR_127, MITK_PP_TUPLE_EAT_4)(o(127, s), p, o, m) # define MITK_PP_FOR_127(s, p, o, m) MITK_PP_IF(p(128, s), m, MITK_PP_TUPLE_EAT_2)(128, s) MITK_PP_IF(p(128, s), MITK_PP_FOR_128, MITK_PP_TUPLE_EAT_4)(o(128, s), p, o, m) # define MITK_PP_FOR_128(s, p, o, m) MITK_PP_IF(p(129, s), m, MITK_PP_TUPLE_EAT_2)(129, s) MITK_PP_IF(p(129, s), MITK_PP_FOR_129, MITK_PP_TUPLE_EAT_4)(o(129, s), p, o, m) # define MITK_PP_FOR_129(s, p, o, m) MITK_PP_IF(p(130, s), m, MITK_PP_TUPLE_EAT_2)(130, s) MITK_PP_IF(p(130, s), MITK_PP_FOR_130, MITK_PP_TUPLE_EAT_4)(o(130, s), p, o, m) # define MITK_PP_FOR_130(s, p, o, m) MITK_PP_IF(p(131, s), m, MITK_PP_TUPLE_EAT_2)(131, s) MITK_PP_IF(p(131, s), MITK_PP_FOR_131, MITK_PP_TUPLE_EAT_4)(o(131, s), p, o, m) # define MITK_PP_FOR_131(s, p, o, m) MITK_PP_IF(p(132, s), m, MITK_PP_TUPLE_EAT_2)(132, s) MITK_PP_IF(p(132, s), MITK_PP_FOR_132, MITK_PP_TUPLE_EAT_4)(o(132, s), p, o, m) # define MITK_PP_FOR_132(s, p, o, m) MITK_PP_IF(p(133, s), m, MITK_PP_TUPLE_EAT_2)(133, s) MITK_PP_IF(p(133, s), MITK_PP_FOR_133, MITK_PP_TUPLE_EAT_4)(o(133, s), p, o, m) # define MITK_PP_FOR_133(s, p, o, m) MITK_PP_IF(p(134, s), m, MITK_PP_TUPLE_EAT_2)(134, s) MITK_PP_IF(p(134, s), MITK_PP_FOR_134, MITK_PP_TUPLE_EAT_4)(o(134, s), p, o, m) # define MITK_PP_FOR_134(s, p, o, m) MITK_PP_IF(p(135, s), m, MITK_PP_TUPLE_EAT_2)(135, s) MITK_PP_IF(p(135, s), MITK_PP_FOR_135, MITK_PP_TUPLE_EAT_4)(o(135, s), p, o, m) # define MITK_PP_FOR_135(s, p, o, m) MITK_PP_IF(p(136, s), m, MITK_PP_TUPLE_EAT_2)(136, s) MITK_PP_IF(p(136, s), MITK_PP_FOR_136, MITK_PP_TUPLE_EAT_4)(o(136, s), p, o, m) # define MITK_PP_FOR_136(s, p, o, m) MITK_PP_IF(p(137, s), m, MITK_PP_TUPLE_EAT_2)(137, s) MITK_PP_IF(p(137, s), MITK_PP_FOR_137, MITK_PP_TUPLE_EAT_4)(o(137, s), p, o, m) # define MITK_PP_FOR_137(s, p, o, m) MITK_PP_IF(p(138, s), m, MITK_PP_TUPLE_EAT_2)(138, s) MITK_PP_IF(p(138, s), MITK_PP_FOR_138, MITK_PP_TUPLE_EAT_4)(o(138, s), p, o, m) # define MITK_PP_FOR_138(s, p, o, m) MITK_PP_IF(p(139, s), m, MITK_PP_TUPLE_EAT_2)(139, s) MITK_PP_IF(p(139, s), MITK_PP_FOR_139, MITK_PP_TUPLE_EAT_4)(o(139, s), p, o, m) # define MITK_PP_FOR_139(s, p, o, m) MITK_PP_IF(p(140, s), m, MITK_PP_TUPLE_EAT_2)(140, s) MITK_PP_IF(p(140, s), MITK_PP_FOR_140, MITK_PP_TUPLE_EAT_4)(o(140, s), p, o, m) # define MITK_PP_FOR_140(s, p, o, m) MITK_PP_IF(p(141, s), m, MITK_PP_TUPLE_EAT_2)(141, s) MITK_PP_IF(p(141, s), MITK_PP_FOR_141, MITK_PP_TUPLE_EAT_4)(o(141, s), p, o, m) # define MITK_PP_FOR_141(s, p, o, m) MITK_PP_IF(p(142, s), m, MITK_PP_TUPLE_EAT_2)(142, s) MITK_PP_IF(p(142, s), MITK_PP_FOR_142, MITK_PP_TUPLE_EAT_4)(o(142, s), p, o, m) # define MITK_PP_FOR_142(s, p, o, m) MITK_PP_IF(p(143, s), m, MITK_PP_TUPLE_EAT_2)(143, s) MITK_PP_IF(p(143, s), MITK_PP_FOR_143, MITK_PP_TUPLE_EAT_4)(o(143, s), p, o, m) # define MITK_PP_FOR_143(s, p, o, m) MITK_PP_IF(p(144, s), m, MITK_PP_TUPLE_EAT_2)(144, s) MITK_PP_IF(p(144, s), MITK_PP_FOR_144, MITK_PP_TUPLE_EAT_4)(o(144, s), p, o, m) # define MITK_PP_FOR_144(s, p, o, m) MITK_PP_IF(p(145, s), m, MITK_PP_TUPLE_EAT_2)(145, s) MITK_PP_IF(p(145, s), MITK_PP_FOR_145, MITK_PP_TUPLE_EAT_4)(o(145, s), p, o, m) # define MITK_PP_FOR_145(s, p, o, m) MITK_PP_IF(p(146, s), m, MITK_PP_TUPLE_EAT_2)(146, s) MITK_PP_IF(p(146, s), MITK_PP_FOR_146, MITK_PP_TUPLE_EAT_4)(o(146, s), p, o, m) # define MITK_PP_FOR_146(s, p, o, m) MITK_PP_IF(p(147, s), m, MITK_PP_TUPLE_EAT_2)(147, s) MITK_PP_IF(p(147, s), MITK_PP_FOR_147, MITK_PP_TUPLE_EAT_4)(o(147, s), p, o, m) # define MITK_PP_FOR_147(s, p, o, m) MITK_PP_IF(p(148, s), m, MITK_PP_TUPLE_EAT_2)(148, s) MITK_PP_IF(p(148, s), MITK_PP_FOR_148, MITK_PP_TUPLE_EAT_4)(o(148, s), p, o, m) # define MITK_PP_FOR_148(s, p, o, m) MITK_PP_IF(p(149, s), m, MITK_PP_TUPLE_EAT_2)(149, s) MITK_PP_IF(p(149, s), MITK_PP_FOR_149, MITK_PP_TUPLE_EAT_4)(o(149, s), p, o, m) # define MITK_PP_FOR_149(s, p, o, m) MITK_PP_IF(p(150, s), m, MITK_PP_TUPLE_EAT_2)(150, s) MITK_PP_IF(p(150, s), MITK_PP_FOR_150, MITK_PP_TUPLE_EAT_4)(o(150, s), p, o, m) # define MITK_PP_FOR_150(s, p, o, m) MITK_PP_IF(p(151, s), m, MITK_PP_TUPLE_EAT_2)(151, s) MITK_PP_IF(p(151, s), MITK_PP_FOR_151, MITK_PP_TUPLE_EAT_4)(o(151, s), p, o, m) # define MITK_PP_FOR_151(s, p, o, m) MITK_PP_IF(p(152, s), m, MITK_PP_TUPLE_EAT_2)(152, s) MITK_PP_IF(p(152, s), MITK_PP_FOR_152, MITK_PP_TUPLE_EAT_4)(o(152, s), p, o, m) # define MITK_PP_FOR_152(s, p, o, m) MITK_PP_IF(p(153, s), m, MITK_PP_TUPLE_EAT_2)(153, s) MITK_PP_IF(p(153, s), MITK_PP_FOR_153, MITK_PP_TUPLE_EAT_4)(o(153, s), p, o, m) # define MITK_PP_FOR_153(s, p, o, m) MITK_PP_IF(p(154, s), m, MITK_PP_TUPLE_EAT_2)(154, s) MITK_PP_IF(p(154, s), MITK_PP_FOR_154, MITK_PP_TUPLE_EAT_4)(o(154, s), p, o, m) # define MITK_PP_FOR_154(s, p, o, m) MITK_PP_IF(p(155, s), m, MITK_PP_TUPLE_EAT_2)(155, s) MITK_PP_IF(p(155, s), MITK_PP_FOR_155, MITK_PP_TUPLE_EAT_4)(o(155, s), p, o, m) # define MITK_PP_FOR_155(s, p, o, m) MITK_PP_IF(p(156, s), m, MITK_PP_TUPLE_EAT_2)(156, s) MITK_PP_IF(p(156, s), MITK_PP_FOR_156, MITK_PP_TUPLE_EAT_4)(o(156, s), p, o, m) # define MITK_PP_FOR_156(s, p, o, m) MITK_PP_IF(p(157, s), m, MITK_PP_TUPLE_EAT_2)(157, s) MITK_PP_IF(p(157, s), MITK_PP_FOR_157, MITK_PP_TUPLE_EAT_4)(o(157, s), p, o, m) # define MITK_PP_FOR_157(s, p, o, m) MITK_PP_IF(p(158, s), m, MITK_PP_TUPLE_EAT_2)(158, s) MITK_PP_IF(p(158, s), MITK_PP_FOR_158, MITK_PP_TUPLE_EAT_4)(o(158, s), p, o, m) # define MITK_PP_FOR_158(s, p, o, m) MITK_PP_IF(p(159, s), m, MITK_PP_TUPLE_EAT_2)(159, s) MITK_PP_IF(p(159, s), MITK_PP_FOR_159, MITK_PP_TUPLE_EAT_4)(o(159, s), p, o, m) # define MITK_PP_FOR_159(s, p, o, m) MITK_PP_IF(p(160, s), m, MITK_PP_TUPLE_EAT_2)(160, s) MITK_PP_IF(p(160, s), MITK_PP_FOR_160, MITK_PP_TUPLE_EAT_4)(o(160, s), p, o, m) # define MITK_PP_FOR_160(s, p, o, m) MITK_PP_IF(p(161, s), m, MITK_PP_TUPLE_EAT_2)(161, s) MITK_PP_IF(p(161, s), MITK_PP_FOR_161, MITK_PP_TUPLE_EAT_4)(o(161, s), p, o, m) # define MITK_PP_FOR_161(s, p, o, m) MITK_PP_IF(p(162, s), m, MITK_PP_TUPLE_EAT_2)(162, s) MITK_PP_IF(p(162, s), MITK_PP_FOR_162, MITK_PP_TUPLE_EAT_4)(o(162, s), p, o, m) # define MITK_PP_FOR_162(s, p, o, m) MITK_PP_IF(p(163, s), m, MITK_PP_TUPLE_EAT_2)(163, s) MITK_PP_IF(p(163, s), MITK_PP_FOR_163, MITK_PP_TUPLE_EAT_4)(o(163, s), p, o, m) # define MITK_PP_FOR_163(s, p, o, m) MITK_PP_IF(p(164, s), m, MITK_PP_TUPLE_EAT_2)(164, s) MITK_PP_IF(p(164, s), MITK_PP_FOR_164, MITK_PP_TUPLE_EAT_4)(o(164, s), p, o, m) # define MITK_PP_FOR_164(s, p, o, m) MITK_PP_IF(p(165, s), m, MITK_PP_TUPLE_EAT_2)(165, s) MITK_PP_IF(p(165, s), MITK_PP_FOR_165, MITK_PP_TUPLE_EAT_4)(o(165, s), p, o, m) # define MITK_PP_FOR_165(s, p, o, m) MITK_PP_IF(p(166, s), m, MITK_PP_TUPLE_EAT_2)(166, s) MITK_PP_IF(p(166, s), MITK_PP_FOR_166, MITK_PP_TUPLE_EAT_4)(o(166, s), p, o, m) # define MITK_PP_FOR_166(s, p, o, m) MITK_PP_IF(p(167, s), m, MITK_PP_TUPLE_EAT_2)(167, s) MITK_PP_IF(p(167, s), MITK_PP_FOR_167, MITK_PP_TUPLE_EAT_4)(o(167, s), p, o, m) # define MITK_PP_FOR_167(s, p, o, m) MITK_PP_IF(p(168, s), m, MITK_PP_TUPLE_EAT_2)(168, s) MITK_PP_IF(p(168, s), MITK_PP_FOR_168, MITK_PP_TUPLE_EAT_4)(o(168, s), p, o, m) # define MITK_PP_FOR_168(s, p, o, m) MITK_PP_IF(p(169, s), m, MITK_PP_TUPLE_EAT_2)(169, s) MITK_PP_IF(p(169, s), MITK_PP_FOR_169, MITK_PP_TUPLE_EAT_4)(o(169, s), p, o, m) # define MITK_PP_FOR_169(s, p, o, m) MITK_PP_IF(p(170, s), m, MITK_PP_TUPLE_EAT_2)(170, s) MITK_PP_IF(p(170, s), MITK_PP_FOR_170, MITK_PP_TUPLE_EAT_4)(o(170, s), p, o, m) # define MITK_PP_FOR_170(s, p, o, m) MITK_PP_IF(p(171, s), m, MITK_PP_TUPLE_EAT_2)(171, s) MITK_PP_IF(p(171, s), MITK_PP_FOR_171, MITK_PP_TUPLE_EAT_4)(o(171, s), p, o, m) # define MITK_PP_FOR_171(s, p, o, m) MITK_PP_IF(p(172, s), m, MITK_PP_TUPLE_EAT_2)(172, s) MITK_PP_IF(p(172, s), MITK_PP_FOR_172, MITK_PP_TUPLE_EAT_4)(o(172, s), p, o, m) # define MITK_PP_FOR_172(s, p, o, m) MITK_PP_IF(p(173, s), m, MITK_PP_TUPLE_EAT_2)(173, s) MITK_PP_IF(p(173, s), MITK_PP_FOR_173, MITK_PP_TUPLE_EAT_4)(o(173, s), p, o, m) # define MITK_PP_FOR_173(s, p, o, m) MITK_PP_IF(p(174, s), m, MITK_PP_TUPLE_EAT_2)(174, s) MITK_PP_IF(p(174, s), MITK_PP_FOR_174, MITK_PP_TUPLE_EAT_4)(o(174, s), p, o, m) # define MITK_PP_FOR_174(s, p, o, m) MITK_PP_IF(p(175, s), m, MITK_PP_TUPLE_EAT_2)(175, s) MITK_PP_IF(p(175, s), MITK_PP_FOR_175, MITK_PP_TUPLE_EAT_4)(o(175, s), p, o, m) # define MITK_PP_FOR_175(s, p, o, m) MITK_PP_IF(p(176, s), m, MITK_PP_TUPLE_EAT_2)(176, s) MITK_PP_IF(p(176, s), MITK_PP_FOR_176, MITK_PP_TUPLE_EAT_4)(o(176, s), p, o, m) # define MITK_PP_FOR_176(s, p, o, m) MITK_PP_IF(p(177, s), m, MITK_PP_TUPLE_EAT_2)(177, s) MITK_PP_IF(p(177, s), MITK_PP_FOR_177, MITK_PP_TUPLE_EAT_4)(o(177, s), p, o, m) # define MITK_PP_FOR_177(s, p, o, m) MITK_PP_IF(p(178, s), m, MITK_PP_TUPLE_EAT_2)(178, s) MITK_PP_IF(p(178, s), MITK_PP_FOR_178, MITK_PP_TUPLE_EAT_4)(o(178, s), p, o, m) # define MITK_PP_FOR_178(s, p, o, m) MITK_PP_IF(p(179, s), m, MITK_PP_TUPLE_EAT_2)(179, s) MITK_PP_IF(p(179, s), MITK_PP_FOR_179, MITK_PP_TUPLE_EAT_4)(o(179, s), p, o, m) # define MITK_PP_FOR_179(s, p, o, m) MITK_PP_IF(p(180, s), m, MITK_PP_TUPLE_EAT_2)(180, s) MITK_PP_IF(p(180, s), MITK_PP_FOR_180, MITK_PP_TUPLE_EAT_4)(o(180, s), p, o, m) # define MITK_PP_FOR_180(s, p, o, m) MITK_PP_IF(p(181, s), m, MITK_PP_TUPLE_EAT_2)(181, s) MITK_PP_IF(p(181, s), MITK_PP_FOR_181, MITK_PP_TUPLE_EAT_4)(o(181, s), p, o, m) # define MITK_PP_FOR_181(s, p, o, m) MITK_PP_IF(p(182, s), m, MITK_PP_TUPLE_EAT_2)(182, s) MITK_PP_IF(p(182, s), MITK_PP_FOR_182, MITK_PP_TUPLE_EAT_4)(o(182, s), p, o, m) # define MITK_PP_FOR_182(s, p, o, m) MITK_PP_IF(p(183, s), m, MITK_PP_TUPLE_EAT_2)(183, s) MITK_PP_IF(p(183, s), MITK_PP_FOR_183, MITK_PP_TUPLE_EAT_4)(o(183, s), p, o, m) # define MITK_PP_FOR_183(s, p, o, m) MITK_PP_IF(p(184, s), m, MITK_PP_TUPLE_EAT_2)(184, s) MITK_PP_IF(p(184, s), MITK_PP_FOR_184, MITK_PP_TUPLE_EAT_4)(o(184, s), p, o, m) # define MITK_PP_FOR_184(s, p, o, m) MITK_PP_IF(p(185, s), m, MITK_PP_TUPLE_EAT_2)(185, s) MITK_PP_IF(p(185, s), MITK_PP_FOR_185, MITK_PP_TUPLE_EAT_4)(o(185, s), p, o, m) # define MITK_PP_FOR_185(s, p, o, m) MITK_PP_IF(p(186, s), m, MITK_PP_TUPLE_EAT_2)(186, s) MITK_PP_IF(p(186, s), MITK_PP_FOR_186, MITK_PP_TUPLE_EAT_4)(o(186, s), p, o, m) # define MITK_PP_FOR_186(s, p, o, m) MITK_PP_IF(p(187, s), m, MITK_PP_TUPLE_EAT_2)(187, s) MITK_PP_IF(p(187, s), MITK_PP_FOR_187, MITK_PP_TUPLE_EAT_4)(o(187, s), p, o, m) # define MITK_PP_FOR_187(s, p, o, m) MITK_PP_IF(p(188, s), m, MITK_PP_TUPLE_EAT_2)(188, s) MITK_PP_IF(p(188, s), MITK_PP_FOR_188, MITK_PP_TUPLE_EAT_4)(o(188, s), p, o, m) # define MITK_PP_FOR_188(s, p, o, m) MITK_PP_IF(p(189, s), m, MITK_PP_TUPLE_EAT_2)(189, s) MITK_PP_IF(p(189, s), MITK_PP_FOR_189, MITK_PP_TUPLE_EAT_4)(o(189, s), p, o, m) # define MITK_PP_FOR_189(s, p, o, m) MITK_PP_IF(p(190, s), m, MITK_PP_TUPLE_EAT_2)(190, s) MITK_PP_IF(p(190, s), MITK_PP_FOR_190, MITK_PP_TUPLE_EAT_4)(o(190, s), p, o, m) # define MITK_PP_FOR_190(s, p, o, m) MITK_PP_IF(p(191, s), m, MITK_PP_TUPLE_EAT_2)(191, s) MITK_PP_IF(p(191, s), MITK_PP_FOR_191, MITK_PP_TUPLE_EAT_4)(o(191, s), p, o, m) # define MITK_PP_FOR_191(s, p, o, m) MITK_PP_IF(p(192, s), m, MITK_PP_TUPLE_EAT_2)(192, s) MITK_PP_IF(p(192, s), MITK_PP_FOR_192, MITK_PP_TUPLE_EAT_4)(o(192, s), p, o, m) # define MITK_PP_FOR_192(s, p, o, m) MITK_PP_IF(p(193, s), m, MITK_PP_TUPLE_EAT_2)(193, s) MITK_PP_IF(p(193, s), MITK_PP_FOR_193, MITK_PP_TUPLE_EAT_4)(o(193, s), p, o, m) # define MITK_PP_FOR_193(s, p, o, m) MITK_PP_IF(p(194, s), m, MITK_PP_TUPLE_EAT_2)(194, s) MITK_PP_IF(p(194, s), MITK_PP_FOR_194, MITK_PP_TUPLE_EAT_4)(o(194, s), p, o, m) # define MITK_PP_FOR_194(s, p, o, m) MITK_PP_IF(p(195, s), m, MITK_PP_TUPLE_EAT_2)(195, s) MITK_PP_IF(p(195, s), MITK_PP_FOR_195, MITK_PP_TUPLE_EAT_4)(o(195, s), p, o, m) # define MITK_PP_FOR_195(s, p, o, m) MITK_PP_IF(p(196, s), m, MITK_PP_TUPLE_EAT_2)(196, s) MITK_PP_IF(p(196, s), MITK_PP_FOR_196, MITK_PP_TUPLE_EAT_4)(o(196, s), p, o, m) # define MITK_PP_FOR_196(s, p, o, m) MITK_PP_IF(p(197, s), m, MITK_PP_TUPLE_EAT_2)(197, s) MITK_PP_IF(p(197, s), MITK_PP_FOR_197, MITK_PP_TUPLE_EAT_4)(o(197, s), p, o, m) # define MITK_PP_FOR_197(s, p, o, m) MITK_PP_IF(p(198, s), m, MITK_PP_TUPLE_EAT_2)(198, s) MITK_PP_IF(p(198, s), MITK_PP_FOR_198, MITK_PP_TUPLE_EAT_4)(o(198, s), p, o, m) # define MITK_PP_FOR_198(s, p, o, m) MITK_PP_IF(p(199, s), m, MITK_PP_TUPLE_EAT_2)(199, s) MITK_PP_IF(p(199, s), MITK_PP_FOR_199, MITK_PP_TUPLE_EAT_4)(o(199, s), p, o, m) # define MITK_PP_FOR_199(s, p, o, m) MITK_PP_IF(p(200, s), m, MITK_PP_TUPLE_EAT_2)(200, s) MITK_PP_IF(p(200, s), MITK_PP_FOR_200, MITK_PP_TUPLE_EAT_4)(o(200, s), p, o, m) # define MITK_PP_FOR_200(s, p, o, m) MITK_PP_IF(p(201, s), m, MITK_PP_TUPLE_EAT_2)(201, s) MITK_PP_IF(p(201, s), MITK_PP_FOR_201, MITK_PP_TUPLE_EAT_4)(o(201, s), p, o, m) # define MITK_PP_FOR_201(s, p, o, m) MITK_PP_IF(p(202, s), m, MITK_PP_TUPLE_EAT_2)(202, s) MITK_PP_IF(p(202, s), MITK_PP_FOR_202, MITK_PP_TUPLE_EAT_4)(o(202, s), p, o, m) # define MITK_PP_FOR_202(s, p, o, m) MITK_PP_IF(p(203, s), m, MITK_PP_TUPLE_EAT_2)(203, s) MITK_PP_IF(p(203, s), MITK_PP_FOR_203, MITK_PP_TUPLE_EAT_4)(o(203, s), p, o, m) # define MITK_PP_FOR_203(s, p, o, m) MITK_PP_IF(p(204, s), m, MITK_PP_TUPLE_EAT_2)(204, s) MITK_PP_IF(p(204, s), MITK_PP_FOR_204, MITK_PP_TUPLE_EAT_4)(o(204, s), p, o, m) # define MITK_PP_FOR_204(s, p, o, m) MITK_PP_IF(p(205, s), m, MITK_PP_TUPLE_EAT_2)(205, s) MITK_PP_IF(p(205, s), MITK_PP_FOR_205, MITK_PP_TUPLE_EAT_4)(o(205, s), p, o, m) # define MITK_PP_FOR_205(s, p, o, m) MITK_PP_IF(p(206, s), m, MITK_PP_TUPLE_EAT_2)(206, s) MITK_PP_IF(p(206, s), MITK_PP_FOR_206, MITK_PP_TUPLE_EAT_4)(o(206, s), p, o, m) # define MITK_PP_FOR_206(s, p, o, m) MITK_PP_IF(p(207, s), m, MITK_PP_TUPLE_EAT_2)(207, s) MITK_PP_IF(p(207, s), MITK_PP_FOR_207, MITK_PP_TUPLE_EAT_4)(o(207, s), p, o, m) # define MITK_PP_FOR_207(s, p, o, m) MITK_PP_IF(p(208, s), m, MITK_PP_TUPLE_EAT_2)(208, s) MITK_PP_IF(p(208, s), MITK_PP_FOR_208, MITK_PP_TUPLE_EAT_4)(o(208, s), p, o, m) # define MITK_PP_FOR_208(s, p, o, m) MITK_PP_IF(p(209, s), m, MITK_PP_TUPLE_EAT_2)(209, s) MITK_PP_IF(p(209, s), MITK_PP_FOR_209, MITK_PP_TUPLE_EAT_4)(o(209, s), p, o, m) # define MITK_PP_FOR_209(s, p, o, m) MITK_PP_IF(p(210, s), m, MITK_PP_TUPLE_EAT_2)(210, s) MITK_PP_IF(p(210, s), MITK_PP_FOR_210, MITK_PP_TUPLE_EAT_4)(o(210, s), p, o, m) # define MITK_PP_FOR_210(s, p, o, m) MITK_PP_IF(p(211, s), m, MITK_PP_TUPLE_EAT_2)(211, s) MITK_PP_IF(p(211, s), MITK_PP_FOR_211, MITK_PP_TUPLE_EAT_4)(o(211, s), p, o, m) # define MITK_PP_FOR_211(s, p, o, m) MITK_PP_IF(p(212, s), m, MITK_PP_TUPLE_EAT_2)(212, s) MITK_PP_IF(p(212, s), MITK_PP_FOR_212, MITK_PP_TUPLE_EAT_4)(o(212, s), p, o, m) # define MITK_PP_FOR_212(s, p, o, m) MITK_PP_IF(p(213, s), m, MITK_PP_TUPLE_EAT_2)(213, s) MITK_PP_IF(p(213, s), MITK_PP_FOR_213, MITK_PP_TUPLE_EAT_4)(o(213, s), p, o, m) # define MITK_PP_FOR_213(s, p, o, m) MITK_PP_IF(p(214, s), m, MITK_PP_TUPLE_EAT_2)(214, s) MITK_PP_IF(p(214, s), MITK_PP_FOR_214, MITK_PP_TUPLE_EAT_4)(o(214, s), p, o, m) # define MITK_PP_FOR_214(s, p, o, m) MITK_PP_IF(p(215, s), m, MITK_PP_TUPLE_EAT_2)(215, s) MITK_PP_IF(p(215, s), MITK_PP_FOR_215, MITK_PP_TUPLE_EAT_4)(o(215, s), p, o, m) # define MITK_PP_FOR_215(s, p, o, m) MITK_PP_IF(p(216, s), m, MITK_PP_TUPLE_EAT_2)(216, s) MITK_PP_IF(p(216, s), MITK_PP_FOR_216, MITK_PP_TUPLE_EAT_4)(o(216, s), p, o, m) # define MITK_PP_FOR_216(s, p, o, m) MITK_PP_IF(p(217, s), m, MITK_PP_TUPLE_EAT_2)(217, s) MITK_PP_IF(p(217, s), MITK_PP_FOR_217, MITK_PP_TUPLE_EAT_4)(o(217, s), p, o, m) # define MITK_PP_FOR_217(s, p, o, m) MITK_PP_IF(p(218, s), m, MITK_PP_TUPLE_EAT_2)(218, s) MITK_PP_IF(p(218, s), MITK_PP_FOR_218, MITK_PP_TUPLE_EAT_4)(o(218, s), p, o, m) # define MITK_PP_FOR_218(s, p, o, m) MITK_PP_IF(p(219, s), m, MITK_PP_TUPLE_EAT_2)(219, s) MITK_PP_IF(p(219, s), MITK_PP_FOR_219, MITK_PP_TUPLE_EAT_4)(o(219, s), p, o, m) # define MITK_PP_FOR_219(s, p, o, m) MITK_PP_IF(p(220, s), m, MITK_PP_TUPLE_EAT_2)(220, s) MITK_PP_IF(p(220, s), MITK_PP_FOR_220, MITK_PP_TUPLE_EAT_4)(o(220, s), p, o, m) # define MITK_PP_FOR_220(s, p, o, m) MITK_PP_IF(p(221, s), m, MITK_PP_TUPLE_EAT_2)(221, s) MITK_PP_IF(p(221, s), MITK_PP_FOR_221, MITK_PP_TUPLE_EAT_4)(o(221, s), p, o, m) # define MITK_PP_FOR_221(s, p, o, m) MITK_PP_IF(p(222, s), m, MITK_PP_TUPLE_EAT_2)(222, s) MITK_PP_IF(p(222, s), MITK_PP_FOR_222, MITK_PP_TUPLE_EAT_4)(o(222, s), p, o, m) # define MITK_PP_FOR_222(s, p, o, m) MITK_PP_IF(p(223, s), m, MITK_PP_TUPLE_EAT_2)(223, s) MITK_PP_IF(p(223, s), MITK_PP_FOR_223, MITK_PP_TUPLE_EAT_4)(o(223, s), p, o, m) # define MITK_PP_FOR_223(s, p, o, m) MITK_PP_IF(p(224, s), m, MITK_PP_TUPLE_EAT_2)(224, s) MITK_PP_IF(p(224, s), MITK_PP_FOR_224, MITK_PP_TUPLE_EAT_4)(o(224, s), p, o, m) # define MITK_PP_FOR_224(s, p, o, m) MITK_PP_IF(p(225, s), m, MITK_PP_TUPLE_EAT_2)(225, s) MITK_PP_IF(p(225, s), MITK_PP_FOR_225, MITK_PP_TUPLE_EAT_4)(o(225, s), p, o, m) # define MITK_PP_FOR_225(s, p, o, m) MITK_PP_IF(p(226, s), m, MITK_PP_TUPLE_EAT_2)(226, s) MITK_PP_IF(p(226, s), MITK_PP_FOR_226, MITK_PP_TUPLE_EAT_4)(o(226, s), p, o, m) # define MITK_PP_FOR_226(s, p, o, m) MITK_PP_IF(p(227, s), m, MITK_PP_TUPLE_EAT_2)(227, s) MITK_PP_IF(p(227, s), MITK_PP_FOR_227, MITK_PP_TUPLE_EAT_4)(o(227, s), p, o, m) # define MITK_PP_FOR_227(s, p, o, m) MITK_PP_IF(p(228, s), m, MITK_PP_TUPLE_EAT_2)(228, s) MITK_PP_IF(p(228, s), MITK_PP_FOR_228, MITK_PP_TUPLE_EAT_4)(o(228, s), p, o, m) # define MITK_PP_FOR_228(s, p, o, m) MITK_PP_IF(p(229, s), m, MITK_PP_TUPLE_EAT_2)(229, s) MITK_PP_IF(p(229, s), MITK_PP_FOR_229, MITK_PP_TUPLE_EAT_4)(o(229, s), p, o, m) # define MITK_PP_FOR_229(s, p, o, m) MITK_PP_IF(p(230, s), m, MITK_PP_TUPLE_EAT_2)(230, s) MITK_PP_IF(p(230, s), MITK_PP_FOR_230, MITK_PP_TUPLE_EAT_4)(o(230, s), p, o, m) # define MITK_PP_FOR_230(s, p, o, m) MITK_PP_IF(p(231, s), m, MITK_PP_TUPLE_EAT_2)(231, s) MITK_PP_IF(p(231, s), MITK_PP_FOR_231, MITK_PP_TUPLE_EAT_4)(o(231, s), p, o, m) # define MITK_PP_FOR_231(s, p, o, m) MITK_PP_IF(p(232, s), m, MITK_PP_TUPLE_EAT_2)(232, s) MITK_PP_IF(p(232, s), MITK_PP_FOR_232, MITK_PP_TUPLE_EAT_4)(o(232, s), p, o, m) # define MITK_PP_FOR_232(s, p, o, m) MITK_PP_IF(p(233, s), m, MITK_PP_TUPLE_EAT_2)(233, s) MITK_PP_IF(p(233, s), MITK_PP_FOR_233, MITK_PP_TUPLE_EAT_4)(o(233, s), p, o, m) # define MITK_PP_FOR_233(s, p, o, m) MITK_PP_IF(p(234, s), m, MITK_PP_TUPLE_EAT_2)(234, s) MITK_PP_IF(p(234, s), MITK_PP_FOR_234, MITK_PP_TUPLE_EAT_4)(o(234, s), p, o, m) # define MITK_PP_FOR_234(s, p, o, m) MITK_PP_IF(p(235, s), m, MITK_PP_TUPLE_EAT_2)(235, s) MITK_PP_IF(p(235, s), MITK_PP_FOR_235, MITK_PP_TUPLE_EAT_4)(o(235, s), p, o, m) # define MITK_PP_FOR_235(s, p, o, m) MITK_PP_IF(p(236, s), m, MITK_PP_TUPLE_EAT_2)(236, s) MITK_PP_IF(p(236, s), MITK_PP_FOR_236, MITK_PP_TUPLE_EAT_4)(o(236, s), p, o, m) # define MITK_PP_FOR_236(s, p, o, m) MITK_PP_IF(p(237, s), m, MITK_PP_TUPLE_EAT_2)(237, s) MITK_PP_IF(p(237, s), MITK_PP_FOR_237, MITK_PP_TUPLE_EAT_4)(o(237, s), p, o, m) # define MITK_PP_FOR_237(s, p, o, m) MITK_PP_IF(p(238, s), m, MITK_PP_TUPLE_EAT_2)(238, s) MITK_PP_IF(p(238, s), MITK_PP_FOR_238, MITK_PP_TUPLE_EAT_4)(o(238, s), p, o, m) # define MITK_PP_FOR_238(s, p, o, m) MITK_PP_IF(p(239, s), m, MITK_PP_TUPLE_EAT_2)(239, s) MITK_PP_IF(p(239, s), MITK_PP_FOR_239, MITK_PP_TUPLE_EAT_4)(o(239, s), p, o, m) # define MITK_PP_FOR_239(s, p, o, m) MITK_PP_IF(p(240, s), m, MITK_PP_TUPLE_EAT_2)(240, s) MITK_PP_IF(p(240, s), MITK_PP_FOR_240, MITK_PP_TUPLE_EAT_4)(o(240, s), p, o, m) # define MITK_PP_FOR_240(s, p, o, m) MITK_PP_IF(p(241, s), m, MITK_PP_TUPLE_EAT_2)(241, s) MITK_PP_IF(p(241, s), MITK_PP_FOR_241, MITK_PP_TUPLE_EAT_4)(o(241, s), p, o, m) # define MITK_PP_FOR_241(s, p, o, m) MITK_PP_IF(p(242, s), m, MITK_PP_TUPLE_EAT_2)(242, s) MITK_PP_IF(p(242, s), MITK_PP_FOR_242, MITK_PP_TUPLE_EAT_4)(o(242, s), p, o, m) # define MITK_PP_FOR_242(s, p, o, m) MITK_PP_IF(p(243, s), m, MITK_PP_TUPLE_EAT_2)(243, s) MITK_PP_IF(p(243, s), MITK_PP_FOR_243, MITK_PP_TUPLE_EAT_4)(o(243, s), p, o, m) # define MITK_PP_FOR_243(s, p, o, m) MITK_PP_IF(p(244, s), m, MITK_PP_TUPLE_EAT_2)(244, s) MITK_PP_IF(p(244, s), MITK_PP_FOR_244, MITK_PP_TUPLE_EAT_4)(o(244, s), p, o, m) # define MITK_PP_FOR_244(s, p, o, m) MITK_PP_IF(p(245, s), m, MITK_PP_TUPLE_EAT_2)(245, s) MITK_PP_IF(p(245, s), MITK_PP_FOR_245, MITK_PP_TUPLE_EAT_4)(o(245, s), p, o, m) # define MITK_PP_FOR_245(s, p, o, m) MITK_PP_IF(p(246, s), m, MITK_PP_TUPLE_EAT_2)(246, s) MITK_PP_IF(p(246, s), MITK_PP_FOR_246, MITK_PP_TUPLE_EAT_4)(o(246, s), p, o, m) # define MITK_PP_FOR_246(s, p, o, m) MITK_PP_IF(p(247, s), m, MITK_PP_TUPLE_EAT_2)(247, s) MITK_PP_IF(p(247, s), MITK_PP_FOR_247, MITK_PP_TUPLE_EAT_4)(o(247, s), p, o, m) # define MITK_PP_FOR_247(s, p, o, m) MITK_PP_IF(p(248, s), m, MITK_PP_TUPLE_EAT_2)(248, s) MITK_PP_IF(p(248, s), MITK_PP_FOR_248, MITK_PP_TUPLE_EAT_4)(o(248, s), p, o, m) # define MITK_PP_FOR_248(s, p, o, m) MITK_PP_IF(p(249, s), m, MITK_PP_TUPLE_EAT_2)(249, s) MITK_PP_IF(p(249, s), MITK_PP_FOR_249, MITK_PP_TUPLE_EAT_4)(o(249, s), p, o, m) # define MITK_PP_FOR_249(s, p, o, m) MITK_PP_IF(p(250, s), m, MITK_PP_TUPLE_EAT_2)(250, s) MITK_PP_IF(p(250, s), MITK_PP_FOR_250, MITK_PP_TUPLE_EAT_4)(o(250, s), p, o, m) # define MITK_PP_FOR_250(s, p, o, m) MITK_PP_IF(p(251, s), m, MITK_PP_TUPLE_EAT_2)(251, s) MITK_PP_IF(p(251, s), MITK_PP_FOR_251, MITK_PP_TUPLE_EAT_4)(o(251, s), p, o, m) # define MITK_PP_FOR_251(s, p, o, m) MITK_PP_IF(p(252, s), m, MITK_PP_TUPLE_EAT_2)(252, s) MITK_PP_IF(p(252, s), MITK_PP_FOR_252, MITK_PP_TUPLE_EAT_4)(o(252, s), p, o, m) # define MITK_PP_FOR_252(s, p, o, m) MITK_PP_IF(p(253, s), m, MITK_PP_TUPLE_EAT_2)(253, s) MITK_PP_IF(p(253, s), MITK_PP_FOR_253, MITK_PP_TUPLE_EAT_4)(o(253, s), p, o, m) # define MITK_PP_FOR_253(s, p, o, m) MITK_PP_IF(p(254, s), m, MITK_PP_TUPLE_EAT_2)(254, s) MITK_PP_IF(p(254, s), MITK_PP_FOR_254, MITK_PP_TUPLE_EAT_4)(o(254, s), p, o, m) # define MITK_PP_FOR_254(s, p, o, m) MITK_PP_IF(p(255, s), m, MITK_PP_TUPLE_EAT_2)(255, s) MITK_PP_IF(p(255, s), MITK_PP_FOR_255, MITK_PP_TUPLE_EAT_4)(o(255, s), p, o, m) # define MITK_PP_FOR_255(s, p, o, m) MITK_PP_IF(p(256, s), m, MITK_PP_TUPLE_EAT_2)(256, s) MITK_PP_IF(p(256, s), MITK_PP_FOR_256, MITK_PP_TUPLE_EAT_4)(o(256, s), p, o, m) # define MITK_PP_FOR_256(s, p, o, m) MITK_PP_IF(p(257, s), m, MITK_PP_TUPLE_EAT_2)(257, s) MITK_PP_IF(p(257, s), MITK_PP_FOR_257, MITK_PP_TUPLE_EAT_4)(o(257, s), p, o, m) # # endif diff --git a/Core/Code/Algorithms/mitkPPRepetitionFor.h b/Core/Code/Algorithms/mitkPPRepetitionFor.h index e2668b5943..4ce86843eb 100644 --- a/Core/Code/Algorithms/mitkPPRepetitionFor.h +++ b/Core/Code/Algorithms/mitkPPRepetitionFor.h @@ -1,306 +1,321 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_REPETITION_FOR_HPP # define MITK_PREPROCESSOR_REPETITION_FOR_HPP # # include "mitkPPCat.h" # include "mitkPPDebugError.h" # include "mitkPPDetailAutoRec.h" # # /* MITK_PP_FOR */ # # if 0 # define MITK_PP_FOR(state, pred, op, macro) # endif # # define MITK_PP_FOR MITK_PP_CAT(MITK_PP_FOR_, MITK_PP_AUTO_REC(MITK_PP_FOR_P, 256)) # # define MITK_PP_FOR_P(n) MITK_PP_CAT(MITK_PP_FOR_CHECK_, MITK_PP_FOR_ ## n(1, MITK_PP_FOR_SR_P, MITK_PP_FOR_SR_O, MITK_PP_FOR_SR_M)) # # define MITK_PP_FOR_SR_P(r, s) s # define MITK_PP_FOR_SR_O(r, s) 0 # define MITK_PP_FOR_SR_M(r, s) MITK_PP_NIL # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # include "mitkPPRepetitionDetailEDGFor.h" # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # include "mitkPPRepetitionDetailMSVCFor.h" # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_DMC() # include "mitkPPRepetitionDetailDMCFor.h" # else # include "mitkPPRepetitionDetailFor.h" # endif # # define MITK_PP_FOR_257(s, p, o, m) MITK_PP_ERROR(0x0002) # # define MITK_PP_FOR_CHECK_MITK_PP_NIL 1 # # define MITK_PP_FOR_CHECK_MITK_PP_FOR_1(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_2(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_3(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_4(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_5(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_6(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_7(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_8(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_9(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_10(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_11(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_12(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_13(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_14(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_15(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_16(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_17(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_18(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_19(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_20(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_21(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_22(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_23(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_24(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_25(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_26(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_27(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_28(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_29(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_30(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_31(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_32(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_33(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_34(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_35(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_36(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_37(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_38(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_39(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_40(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_41(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_42(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_43(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_44(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_45(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_46(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_47(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_48(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_49(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_50(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_51(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_52(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_53(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_54(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_55(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_56(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_57(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_58(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_59(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_60(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_61(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_62(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_63(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_64(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_65(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_66(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_67(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_68(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_69(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_70(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_71(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_72(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_73(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_74(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_75(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_76(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_77(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_78(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_79(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_80(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_81(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_82(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_83(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_84(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_85(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_86(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_87(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_88(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_89(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_90(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_91(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_92(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_93(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_94(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_95(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_96(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_97(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_98(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_99(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_100(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_101(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_102(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_103(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_104(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_105(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_106(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_107(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_108(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_109(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_110(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_111(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_112(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_113(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_114(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_115(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_116(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_117(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_118(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_119(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_120(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_121(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_122(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_123(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_124(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_125(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_126(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_127(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_128(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_129(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_130(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_131(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_132(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_133(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_134(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_135(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_136(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_137(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_138(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_139(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_140(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_141(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_142(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_143(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_144(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_145(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_146(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_147(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_148(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_149(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_150(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_151(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_152(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_153(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_154(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_155(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_156(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_157(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_158(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_159(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_160(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_161(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_162(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_163(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_164(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_165(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_166(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_167(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_168(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_169(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_170(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_171(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_172(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_173(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_174(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_175(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_176(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_177(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_178(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_179(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_180(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_181(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_182(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_183(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_184(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_185(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_186(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_187(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_188(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_189(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_190(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_191(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_192(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_193(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_194(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_195(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_196(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_197(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_198(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_199(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_200(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_201(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_202(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_203(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_204(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_205(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_206(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_207(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_208(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_209(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_210(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_211(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_212(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_213(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_214(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_215(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_216(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_217(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_218(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_219(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_220(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_221(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_222(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_223(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_224(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_225(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_226(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_227(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_228(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_229(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_230(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_231(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_232(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_233(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_234(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_235(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_236(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_237(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_238(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_239(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_240(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_241(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_242(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_243(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_244(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_245(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_246(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_247(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_248(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_249(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_250(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_251(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_252(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_253(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_254(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_255(s, p, o, m) 0 # define MITK_PP_FOR_CHECK_MITK_PP_FOR_256(s, p, o, m) 0 # # endif diff --git a/Core/Code/Algorithms/mitkPPSeq.h b/Core/Code/Algorithms/mitkPPSeq.h index f6f390cd74..95d974bd81 100644 --- a/Core/Code/Algorithms/mitkPPSeq.h +++ b/Core/Code/Algorithms/mitkPPSeq.h @@ -1,44 +1,59 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_SEQ_HPP # define MITK_PREPROCESSOR_SEQ_SEQ_HPP # # include "mitkPPConfig.h" # include "mitkPPSeqElem.h" # # /* MITK_PP_SEQ_HEAD */ # # define MITK_PP_SEQ_HEAD(seq) MITK_PP_SEQ_ELEM(0, seq) # # /* MITK_PP_SEQ_TAIL */ # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_TAIL(seq) MITK_PP_SEQ_TAIL_1((seq)) # define MITK_PP_SEQ_TAIL_1(par) MITK_PP_SEQ_TAIL_2 ## par # define MITK_PP_SEQ_TAIL_2(seq) MITK_PP_SEQ_TAIL_I ## seq # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_SEQ_TAIL(seq) MITK_PP_SEQ_TAIL_ID(MITK_PP_SEQ_TAIL_I seq) # define MITK_PP_SEQ_TAIL_ID(id) id # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_TAIL(seq) MITK_PP_SEQ_TAIL_D(seq) # define MITK_PP_SEQ_TAIL_D(seq) MITK_PP_SEQ_TAIL_I seq # else # define MITK_PP_SEQ_TAIL(seq) MITK_PP_SEQ_TAIL_I seq # endif # # define MITK_PP_SEQ_TAIL_I(x) # # /* MITK_PP_SEQ_NIL */ # # define MITK_PP_SEQ_NIL(x) (x) # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqElem.h b/Core/Code/Algorithms/mitkPPSeqElem.h index 5877c80868..77c09d2ad4 100644 --- a/Core/Code/Algorithms/mitkPPSeqElem.h +++ b/Core/Code/Algorithms/mitkPPSeqElem.h @@ -1,304 +1,319 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_ELEM_HPP # define MITK_PREPROCESSOR_SEQ_ELEM_HPP # # include "mitkPPCat.h" # include "mitkPPConfig.h" # include "mitkPPFacilitiesEmpty.h" # # /* MITK_PP_SEQ_ELEM */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_ELEM(i, seq) MITK_PP_SEQ_ELEM_I(i, seq) # else # define MITK_PP_SEQ_ELEM(i, seq) MITK_PP_SEQ_ELEM_I((i, seq)) # endif # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_SEQ_ELEM_I(i, seq) MITK_PP_SEQ_ELEM_II((MITK_PP_SEQ_ELEM_ ## i seq)) # define MITK_PP_SEQ_ELEM_II(res) MITK_PP_SEQ_ELEM_IV(MITK_PP_SEQ_ELEM_III res) # define MITK_PP_SEQ_ELEM_III(x, _) x MITK_PP_EMPTY() # define MITK_PP_SEQ_ELEM_IV(x) x # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_ELEM_I(par) MITK_PP_SEQ_ELEM_II ## par # define MITK_PP_SEQ_ELEM_II(i, seq) MITK_PP_SEQ_ELEM_III(MITK_PP_SEQ_ELEM_ ## i ## seq) # define MITK_PP_SEQ_ELEM_III(im) MITK_PP_SEQ_ELEM_IV(im) # define MITK_PP_SEQ_ELEM_IV(x, _) x # else # if defined(__IBMC__) || defined(__IBMCPP__) # define MITK_PP_SEQ_ELEM_I(i, seq) MITK_PP_SEQ_ELEM_II(MITK_PP_CAT(MITK_PP_SEQ_ELEM_ ## i, seq)) # else # define MITK_PP_SEQ_ELEM_I(i, seq) MITK_PP_SEQ_ELEM_II(MITK_PP_SEQ_ELEM_ ## i seq) # endif # define MITK_PP_SEQ_ELEM_II(im) MITK_PP_SEQ_ELEM_III(im) # define MITK_PP_SEQ_ELEM_III(x, _) x # endif # # define MITK_PP_SEQ_ELEM_0(x) x, MITK_PP_NIL # define MITK_PP_SEQ_ELEM_1(_) MITK_PP_SEQ_ELEM_0 # define MITK_PP_SEQ_ELEM_2(_) MITK_PP_SEQ_ELEM_1 # define MITK_PP_SEQ_ELEM_3(_) MITK_PP_SEQ_ELEM_2 # define MITK_PP_SEQ_ELEM_4(_) MITK_PP_SEQ_ELEM_3 # define MITK_PP_SEQ_ELEM_5(_) MITK_PP_SEQ_ELEM_4 # define MITK_PP_SEQ_ELEM_6(_) MITK_PP_SEQ_ELEM_5 # define MITK_PP_SEQ_ELEM_7(_) MITK_PP_SEQ_ELEM_6 # define MITK_PP_SEQ_ELEM_8(_) MITK_PP_SEQ_ELEM_7 # define MITK_PP_SEQ_ELEM_9(_) MITK_PP_SEQ_ELEM_8 # define MITK_PP_SEQ_ELEM_10(_) MITK_PP_SEQ_ELEM_9 # define MITK_PP_SEQ_ELEM_11(_) MITK_PP_SEQ_ELEM_10 # define MITK_PP_SEQ_ELEM_12(_) MITK_PP_SEQ_ELEM_11 # define MITK_PP_SEQ_ELEM_13(_) MITK_PP_SEQ_ELEM_12 # define MITK_PP_SEQ_ELEM_14(_) MITK_PP_SEQ_ELEM_13 # define MITK_PP_SEQ_ELEM_15(_) MITK_PP_SEQ_ELEM_14 # define MITK_PP_SEQ_ELEM_16(_) MITK_PP_SEQ_ELEM_15 # define MITK_PP_SEQ_ELEM_17(_) MITK_PP_SEQ_ELEM_16 # define MITK_PP_SEQ_ELEM_18(_) MITK_PP_SEQ_ELEM_17 # define MITK_PP_SEQ_ELEM_19(_) MITK_PP_SEQ_ELEM_18 # define MITK_PP_SEQ_ELEM_20(_) MITK_PP_SEQ_ELEM_19 # define MITK_PP_SEQ_ELEM_21(_) MITK_PP_SEQ_ELEM_20 # define MITK_PP_SEQ_ELEM_22(_) MITK_PP_SEQ_ELEM_21 # define MITK_PP_SEQ_ELEM_23(_) MITK_PP_SEQ_ELEM_22 # define MITK_PP_SEQ_ELEM_24(_) MITK_PP_SEQ_ELEM_23 # define MITK_PP_SEQ_ELEM_25(_) MITK_PP_SEQ_ELEM_24 # define MITK_PP_SEQ_ELEM_26(_) MITK_PP_SEQ_ELEM_25 # define MITK_PP_SEQ_ELEM_27(_) MITK_PP_SEQ_ELEM_26 # define MITK_PP_SEQ_ELEM_28(_) MITK_PP_SEQ_ELEM_27 # define MITK_PP_SEQ_ELEM_29(_) MITK_PP_SEQ_ELEM_28 # define MITK_PP_SEQ_ELEM_30(_) MITK_PP_SEQ_ELEM_29 # define MITK_PP_SEQ_ELEM_31(_) MITK_PP_SEQ_ELEM_30 # define MITK_PP_SEQ_ELEM_32(_) MITK_PP_SEQ_ELEM_31 # define MITK_PP_SEQ_ELEM_33(_) MITK_PP_SEQ_ELEM_32 # define MITK_PP_SEQ_ELEM_34(_) MITK_PP_SEQ_ELEM_33 # define MITK_PP_SEQ_ELEM_35(_) MITK_PP_SEQ_ELEM_34 # define MITK_PP_SEQ_ELEM_36(_) MITK_PP_SEQ_ELEM_35 # define MITK_PP_SEQ_ELEM_37(_) MITK_PP_SEQ_ELEM_36 # define MITK_PP_SEQ_ELEM_38(_) MITK_PP_SEQ_ELEM_37 # define MITK_PP_SEQ_ELEM_39(_) MITK_PP_SEQ_ELEM_38 # define MITK_PP_SEQ_ELEM_40(_) MITK_PP_SEQ_ELEM_39 # define MITK_PP_SEQ_ELEM_41(_) MITK_PP_SEQ_ELEM_40 # define MITK_PP_SEQ_ELEM_42(_) MITK_PP_SEQ_ELEM_41 # define MITK_PP_SEQ_ELEM_43(_) MITK_PP_SEQ_ELEM_42 # define MITK_PP_SEQ_ELEM_44(_) MITK_PP_SEQ_ELEM_43 # define MITK_PP_SEQ_ELEM_45(_) MITK_PP_SEQ_ELEM_44 # define MITK_PP_SEQ_ELEM_46(_) MITK_PP_SEQ_ELEM_45 # define MITK_PP_SEQ_ELEM_47(_) MITK_PP_SEQ_ELEM_46 # define MITK_PP_SEQ_ELEM_48(_) MITK_PP_SEQ_ELEM_47 # define MITK_PP_SEQ_ELEM_49(_) MITK_PP_SEQ_ELEM_48 # define MITK_PP_SEQ_ELEM_50(_) MITK_PP_SEQ_ELEM_49 # define MITK_PP_SEQ_ELEM_51(_) MITK_PP_SEQ_ELEM_50 # define MITK_PP_SEQ_ELEM_52(_) MITK_PP_SEQ_ELEM_51 # define MITK_PP_SEQ_ELEM_53(_) MITK_PP_SEQ_ELEM_52 # define MITK_PP_SEQ_ELEM_54(_) MITK_PP_SEQ_ELEM_53 # define MITK_PP_SEQ_ELEM_55(_) MITK_PP_SEQ_ELEM_54 # define MITK_PP_SEQ_ELEM_56(_) MITK_PP_SEQ_ELEM_55 # define MITK_PP_SEQ_ELEM_57(_) MITK_PP_SEQ_ELEM_56 # define MITK_PP_SEQ_ELEM_58(_) MITK_PP_SEQ_ELEM_57 # define MITK_PP_SEQ_ELEM_59(_) MITK_PP_SEQ_ELEM_58 # define MITK_PP_SEQ_ELEM_60(_) MITK_PP_SEQ_ELEM_59 # define MITK_PP_SEQ_ELEM_61(_) MITK_PP_SEQ_ELEM_60 # define MITK_PP_SEQ_ELEM_62(_) MITK_PP_SEQ_ELEM_61 # define MITK_PP_SEQ_ELEM_63(_) MITK_PP_SEQ_ELEM_62 # define MITK_PP_SEQ_ELEM_64(_) MITK_PP_SEQ_ELEM_63 # define MITK_PP_SEQ_ELEM_65(_) MITK_PP_SEQ_ELEM_64 # define MITK_PP_SEQ_ELEM_66(_) MITK_PP_SEQ_ELEM_65 # define MITK_PP_SEQ_ELEM_67(_) MITK_PP_SEQ_ELEM_66 # define MITK_PP_SEQ_ELEM_68(_) MITK_PP_SEQ_ELEM_67 # define MITK_PP_SEQ_ELEM_69(_) MITK_PP_SEQ_ELEM_68 # define MITK_PP_SEQ_ELEM_70(_) MITK_PP_SEQ_ELEM_69 # define MITK_PP_SEQ_ELEM_71(_) MITK_PP_SEQ_ELEM_70 # define MITK_PP_SEQ_ELEM_72(_) MITK_PP_SEQ_ELEM_71 # define MITK_PP_SEQ_ELEM_73(_) MITK_PP_SEQ_ELEM_72 # define MITK_PP_SEQ_ELEM_74(_) MITK_PP_SEQ_ELEM_73 # define MITK_PP_SEQ_ELEM_75(_) MITK_PP_SEQ_ELEM_74 # define MITK_PP_SEQ_ELEM_76(_) MITK_PP_SEQ_ELEM_75 # define MITK_PP_SEQ_ELEM_77(_) MITK_PP_SEQ_ELEM_76 # define MITK_PP_SEQ_ELEM_78(_) MITK_PP_SEQ_ELEM_77 # define MITK_PP_SEQ_ELEM_79(_) MITK_PP_SEQ_ELEM_78 # define MITK_PP_SEQ_ELEM_80(_) MITK_PP_SEQ_ELEM_79 # define MITK_PP_SEQ_ELEM_81(_) MITK_PP_SEQ_ELEM_80 # define MITK_PP_SEQ_ELEM_82(_) MITK_PP_SEQ_ELEM_81 # define MITK_PP_SEQ_ELEM_83(_) MITK_PP_SEQ_ELEM_82 # define MITK_PP_SEQ_ELEM_84(_) MITK_PP_SEQ_ELEM_83 # define MITK_PP_SEQ_ELEM_85(_) MITK_PP_SEQ_ELEM_84 # define MITK_PP_SEQ_ELEM_86(_) MITK_PP_SEQ_ELEM_85 # define MITK_PP_SEQ_ELEM_87(_) MITK_PP_SEQ_ELEM_86 # define MITK_PP_SEQ_ELEM_88(_) MITK_PP_SEQ_ELEM_87 # define MITK_PP_SEQ_ELEM_89(_) MITK_PP_SEQ_ELEM_88 # define MITK_PP_SEQ_ELEM_90(_) MITK_PP_SEQ_ELEM_89 # define MITK_PP_SEQ_ELEM_91(_) MITK_PP_SEQ_ELEM_90 # define MITK_PP_SEQ_ELEM_92(_) MITK_PP_SEQ_ELEM_91 # define MITK_PP_SEQ_ELEM_93(_) MITK_PP_SEQ_ELEM_92 # define MITK_PP_SEQ_ELEM_94(_) MITK_PP_SEQ_ELEM_93 # define MITK_PP_SEQ_ELEM_95(_) MITK_PP_SEQ_ELEM_94 # define MITK_PP_SEQ_ELEM_96(_) MITK_PP_SEQ_ELEM_95 # define MITK_PP_SEQ_ELEM_97(_) MITK_PP_SEQ_ELEM_96 # define MITK_PP_SEQ_ELEM_98(_) MITK_PP_SEQ_ELEM_97 # define MITK_PP_SEQ_ELEM_99(_) MITK_PP_SEQ_ELEM_98 # define MITK_PP_SEQ_ELEM_100(_) MITK_PP_SEQ_ELEM_99 # define MITK_PP_SEQ_ELEM_101(_) MITK_PP_SEQ_ELEM_100 # define MITK_PP_SEQ_ELEM_102(_) MITK_PP_SEQ_ELEM_101 # define MITK_PP_SEQ_ELEM_103(_) MITK_PP_SEQ_ELEM_102 # define MITK_PP_SEQ_ELEM_104(_) MITK_PP_SEQ_ELEM_103 # define MITK_PP_SEQ_ELEM_105(_) MITK_PP_SEQ_ELEM_104 # define MITK_PP_SEQ_ELEM_106(_) MITK_PP_SEQ_ELEM_105 # define MITK_PP_SEQ_ELEM_107(_) MITK_PP_SEQ_ELEM_106 # define MITK_PP_SEQ_ELEM_108(_) MITK_PP_SEQ_ELEM_107 # define MITK_PP_SEQ_ELEM_109(_) MITK_PP_SEQ_ELEM_108 # define MITK_PP_SEQ_ELEM_110(_) MITK_PP_SEQ_ELEM_109 # define MITK_PP_SEQ_ELEM_111(_) MITK_PP_SEQ_ELEM_110 # define MITK_PP_SEQ_ELEM_112(_) MITK_PP_SEQ_ELEM_111 # define MITK_PP_SEQ_ELEM_113(_) MITK_PP_SEQ_ELEM_112 # define MITK_PP_SEQ_ELEM_114(_) MITK_PP_SEQ_ELEM_113 # define MITK_PP_SEQ_ELEM_115(_) MITK_PP_SEQ_ELEM_114 # define MITK_PP_SEQ_ELEM_116(_) MITK_PP_SEQ_ELEM_115 # define MITK_PP_SEQ_ELEM_117(_) MITK_PP_SEQ_ELEM_116 # define MITK_PP_SEQ_ELEM_118(_) MITK_PP_SEQ_ELEM_117 # define MITK_PP_SEQ_ELEM_119(_) MITK_PP_SEQ_ELEM_118 # define MITK_PP_SEQ_ELEM_120(_) MITK_PP_SEQ_ELEM_119 # define MITK_PP_SEQ_ELEM_121(_) MITK_PP_SEQ_ELEM_120 # define MITK_PP_SEQ_ELEM_122(_) MITK_PP_SEQ_ELEM_121 # define MITK_PP_SEQ_ELEM_123(_) MITK_PP_SEQ_ELEM_122 # define MITK_PP_SEQ_ELEM_124(_) MITK_PP_SEQ_ELEM_123 # define MITK_PP_SEQ_ELEM_125(_) MITK_PP_SEQ_ELEM_124 # define MITK_PP_SEQ_ELEM_126(_) MITK_PP_SEQ_ELEM_125 # define MITK_PP_SEQ_ELEM_127(_) MITK_PP_SEQ_ELEM_126 # define MITK_PP_SEQ_ELEM_128(_) MITK_PP_SEQ_ELEM_127 # define MITK_PP_SEQ_ELEM_129(_) MITK_PP_SEQ_ELEM_128 # define MITK_PP_SEQ_ELEM_130(_) MITK_PP_SEQ_ELEM_129 # define MITK_PP_SEQ_ELEM_131(_) MITK_PP_SEQ_ELEM_130 # define MITK_PP_SEQ_ELEM_132(_) MITK_PP_SEQ_ELEM_131 # define MITK_PP_SEQ_ELEM_133(_) MITK_PP_SEQ_ELEM_132 # define MITK_PP_SEQ_ELEM_134(_) MITK_PP_SEQ_ELEM_133 # define MITK_PP_SEQ_ELEM_135(_) MITK_PP_SEQ_ELEM_134 # define MITK_PP_SEQ_ELEM_136(_) MITK_PP_SEQ_ELEM_135 # define MITK_PP_SEQ_ELEM_137(_) MITK_PP_SEQ_ELEM_136 # define MITK_PP_SEQ_ELEM_138(_) MITK_PP_SEQ_ELEM_137 # define MITK_PP_SEQ_ELEM_139(_) MITK_PP_SEQ_ELEM_138 # define MITK_PP_SEQ_ELEM_140(_) MITK_PP_SEQ_ELEM_139 # define MITK_PP_SEQ_ELEM_141(_) MITK_PP_SEQ_ELEM_140 # define MITK_PP_SEQ_ELEM_142(_) MITK_PP_SEQ_ELEM_141 # define MITK_PP_SEQ_ELEM_143(_) MITK_PP_SEQ_ELEM_142 # define MITK_PP_SEQ_ELEM_144(_) MITK_PP_SEQ_ELEM_143 # define MITK_PP_SEQ_ELEM_145(_) MITK_PP_SEQ_ELEM_144 # define MITK_PP_SEQ_ELEM_146(_) MITK_PP_SEQ_ELEM_145 # define MITK_PP_SEQ_ELEM_147(_) MITK_PP_SEQ_ELEM_146 # define MITK_PP_SEQ_ELEM_148(_) MITK_PP_SEQ_ELEM_147 # define MITK_PP_SEQ_ELEM_149(_) MITK_PP_SEQ_ELEM_148 # define MITK_PP_SEQ_ELEM_150(_) MITK_PP_SEQ_ELEM_149 # define MITK_PP_SEQ_ELEM_151(_) MITK_PP_SEQ_ELEM_150 # define MITK_PP_SEQ_ELEM_152(_) MITK_PP_SEQ_ELEM_151 # define MITK_PP_SEQ_ELEM_153(_) MITK_PP_SEQ_ELEM_152 # define MITK_PP_SEQ_ELEM_154(_) MITK_PP_SEQ_ELEM_153 # define MITK_PP_SEQ_ELEM_155(_) MITK_PP_SEQ_ELEM_154 # define MITK_PP_SEQ_ELEM_156(_) MITK_PP_SEQ_ELEM_155 # define MITK_PP_SEQ_ELEM_157(_) MITK_PP_SEQ_ELEM_156 # define MITK_PP_SEQ_ELEM_158(_) MITK_PP_SEQ_ELEM_157 # define MITK_PP_SEQ_ELEM_159(_) MITK_PP_SEQ_ELEM_158 # define MITK_PP_SEQ_ELEM_160(_) MITK_PP_SEQ_ELEM_159 # define MITK_PP_SEQ_ELEM_161(_) MITK_PP_SEQ_ELEM_160 # define MITK_PP_SEQ_ELEM_162(_) MITK_PP_SEQ_ELEM_161 # define MITK_PP_SEQ_ELEM_163(_) MITK_PP_SEQ_ELEM_162 # define MITK_PP_SEQ_ELEM_164(_) MITK_PP_SEQ_ELEM_163 # define MITK_PP_SEQ_ELEM_165(_) MITK_PP_SEQ_ELEM_164 # define MITK_PP_SEQ_ELEM_166(_) MITK_PP_SEQ_ELEM_165 # define MITK_PP_SEQ_ELEM_167(_) MITK_PP_SEQ_ELEM_166 # define MITK_PP_SEQ_ELEM_168(_) MITK_PP_SEQ_ELEM_167 # define MITK_PP_SEQ_ELEM_169(_) MITK_PP_SEQ_ELEM_168 # define MITK_PP_SEQ_ELEM_170(_) MITK_PP_SEQ_ELEM_169 # define MITK_PP_SEQ_ELEM_171(_) MITK_PP_SEQ_ELEM_170 # define MITK_PP_SEQ_ELEM_172(_) MITK_PP_SEQ_ELEM_171 # define MITK_PP_SEQ_ELEM_173(_) MITK_PP_SEQ_ELEM_172 # define MITK_PP_SEQ_ELEM_174(_) MITK_PP_SEQ_ELEM_173 # define MITK_PP_SEQ_ELEM_175(_) MITK_PP_SEQ_ELEM_174 # define MITK_PP_SEQ_ELEM_176(_) MITK_PP_SEQ_ELEM_175 # define MITK_PP_SEQ_ELEM_177(_) MITK_PP_SEQ_ELEM_176 # define MITK_PP_SEQ_ELEM_178(_) MITK_PP_SEQ_ELEM_177 # define MITK_PP_SEQ_ELEM_179(_) MITK_PP_SEQ_ELEM_178 # define MITK_PP_SEQ_ELEM_180(_) MITK_PP_SEQ_ELEM_179 # define MITK_PP_SEQ_ELEM_181(_) MITK_PP_SEQ_ELEM_180 # define MITK_PP_SEQ_ELEM_182(_) MITK_PP_SEQ_ELEM_181 # define MITK_PP_SEQ_ELEM_183(_) MITK_PP_SEQ_ELEM_182 # define MITK_PP_SEQ_ELEM_184(_) MITK_PP_SEQ_ELEM_183 # define MITK_PP_SEQ_ELEM_185(_) MITK_PP_SEQ_ELEM_184 # define MITK_PP_SEQ_ELEM_186(_) MITK_PP_SEQ_ELEM_185 # define MITK_PP_SEQ_ELEM_187(_) MITK_PP_SEQ_ELEM_186 # define MITK_PP_SEQ_ELEM_188(_) MITK_PP_SEQ_ELEM_187 # define MITK_PP_SEQ_ELEM_189(_) MITK_PP_SEQ_ELEM_188 # define MITK_PP_SEQ_ELEM_190(_) MITK_PP_SEQ_ELEM_189 # define MITK_PP_SEQ_ELEM_191(_) MITK_PP_SEQ_ELEM_190 # define MITK_PP_SEQ_ELEM_192(_) MITK_PP_SEQ_ELEM_191 # define MITK_PP_SEQ_ELEM_193(_) MITK_PP_SEQ_ELEM_192 # define MITK_PP_SEQ_ELEM_194(_) MITK_PP_SEQ_ELEM_193 # define MITK_PP_SEQ_ELEM_195(_) MITK_PP_SEQ_ELEM_194 # define MITK_PP_SEQ_ELEM_196(_) MITK_PP_SEQ_ELEM_195 # define MITK_PP_SEQ_ELEM_197(_) MITK_PP_SEQ_ELEM_196 # define MITK_PP_SEQ_ELEM_198(_) MITK_PP_SEQ_ELEM_197 # define MITK_PP_SEQ_ELEM_199(_) MITK_PP_SEQ_ELEM_198 # define MITK_PP_SEQ_ELEM_200(_) MITK_PP_SEQ_ELEM_199 # define MITK_PP_SEQ_ELEM_201(_) MITK_PP_SEQ_ELEM_200 # define MITK_PP_SEQ_ELEM_202(_) MITK_PP_SEQ_ELEM_201 # define MITK_PP_SEQ_ELEM_203(_) MITK_PP_SEQ_ELEM_202 # define MITK_PP_SEQ_ELEM_204(_) MITK_PP_SEQ_ELEM_203 # define MITK_PP_SEQ_ELEM_205(_) MITK_PP_SEQ_ELEM_204 # define MITK_PP_SEQ_ELEM_206(_) MITK_PP_SEQ_ELEM_205 # define MITK_PP_SEQ_ELEM_207(_) MITK_PP_SEQ_ELEM_206 # define MITK_PP_SEQ_ELEM_208(_) MITK_PP_SEQ_ELEM_207 # define MITK_PP_SEQ_ELEM_209(_) MITK_PP_SEQ_ELEM_208 # define MITK_PP_SEQ_ELEM_210(_) MITK_PP_SEQ_ELEM_209 # define MITK_PP_SEQ_ELEM_211(_) MITK_PP_SEQ_ELEM_210 # define MITK_PP_SEQ_ELEM_212(_) MITK_PP_SEQ_ELEM_211 # define MITK_PP_SEQ_ELEM_213(_) MITK_PP_SEQ_ELEM_212 # define MITK_PP_SEQ_ELEM_214(_) MITK_PP_SEQ_ELEM_213 # define MITK_PP_SEQ_ELEM_215(_) MITK_PP_SEQ_ELEM_214 # define MITK_PP_SEQ_ELEM_216(_) MITK_PP_SEQ_ELEM_215 # define MITK_PP_SEQ_ELEM_217(_) MITK_PP_SEQ_ELEM_216 # define MITK_PP_SEQ_ELEM_218(_) MITK_PP_SEQ_ELEM_217 # define MITK_PP_SEQ_ELEM_219(_) MITK_PP_SEQ_ELEM_218 # define MITK_PP_SEQ_ELEM_220(_) MITK_PP_SEQ_ELEM_219 # define MITK_PP_SEQ_ELEM_221(_) MITK_PP_SEQ_ELEM_220 # define MITK_PP_SEQ_ELEM_222(_) MITK_PP_SEQ_ELEM_221 # define MITK_PP_SEQ_ELEM_223(_) MITK_PP_SEQ_ELEM_222 # define MITK_PP_SEQ_ELEM_224(_) MITK_PP_SEQ_ELEM_223 # define MITK_PP_SEQ_ELEM_225(_) MITK_PP_SEQ_ELEM_224 # define MITK_PP_SEQ_ELEM_226(_) MITK_PP_SEQ_ELEM_225 # define MITK_PP_SEQ_ELEM_227(_) MITK_PP_SEQ_ELEM_226 # define MITK_PP_SEQ_ELEM_228(_) MITK_PP_SEQ_ELEM_227 # define MITK_PP_SEQ_ELEM_229(_) MITK_PP_SEQ_ELEM_228 # define MITK_PP_SEQ_ELEM_230(_) MITK_PP_SEQ_ELEM_229 # define MITK_PP_SEQ_ELEM_231(_) MITK_PP_SEQ_ELEM_230 # define MITK_PP_SEQ_ELEM_232(_) MITK_PP_SEQ_ELEM_231 # define MITK_PP_SEQ_ELEM_233(_) MITK_PP_SEQ_ELEM_232 # define MITK_PP_SEQ_ELEM_234(_) MITK_PP_SEQ_ELEM_233 # define MITK_PP_SEQ_ELEM_235(_) MITK_PP_SEQ_ELEM_234 # define MITK_PP_SEQ_ELEM_236(_) MITK_PP_SEQ_ELEM_235 # define MITK_PP_SEQ_ELEM_237(_) MITK_PP_SEQ_ELEM_236 # define MITK_PP_SEQ_ELEM_238(_) MITK_PP_SEQ_ELEM_237 # define MITK_PP_SEQ_ELEM_239(_) MITK_PP_SEQ_ELEM_238 # define MITK_PP_SEQ_ELEM_240(_) MITK_PP_SEQ_ELEM_239 # define MITK_PP_SEQ_ELEM_241(_) MITK_PP_SEQ_ELEM_240 # define MITK_PP_SEQ_ELEM_242(_) MITK_PP_SEQ_ELEM_241 # define MITK_PP_SEQ_ELEM_243(_) MITK_PP_SEQ_ELEM_242 # define MITK_PP_SEQ_ELEM_244(_) MITK_PP_SEQ_ELEM_243 # define MITK_PP_SEQ_ELEM_245(_) MITK_PP_SEQ_ELEM_244 # define MITK_PP_SEQ_ELEM_246(_) MITK_PP_SEQ_ELEM_245 # define MITK_PP_SEQ_ELEM_247(_) MITK_PP_SEQ_ELEM_246 # define MITK_PP_SEQ_ELEM_248(_) MITK_PP_SEQ_ELEM_247 # define MITK_PP_SEQ_ELEM_249(_) MITK_PP_SEQ_ELEM_248 # define MITK_PP_SEQ_ELEM_250(_) MITK_PP_SEQ_ELEM_249 # define MITK_PP_SEQ_ELEM_251(_) MITK_PP_SEQ_ELEM_250 # define MITK_PP_SEQ_ELEM_252(_) MITK_PP_SEQ_ELEM_251 # define MITK_PP_SEQ_ELEM_253(_) MITK_PP_SEQ_ELEM_252 # define MITK_PP_SEQ_ELEM_254(_) MITK_PP_SEQ_ELEM_253 # define MITK_PP_SEQ_ELEM_255(_) MITK_PP_SEQ_ELEM_254 # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqEnum.h b/Core/Code/Algorithms/mitkPPSeqEnum.h index f9cfc97796..a23c92c12a 100644 --- a/Core/Code/Algorithms/mitkPPSeqEnum.h +++ b/Core/Code/Algorithms/mitkPPSeqEnum.h @@ -1,288 +1,303 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_ENUM_HPP # define MITK_PREPROCESSOR_SEQ_ENUM_HPP # # include "mitkPPCat.h" # include "mitkPPConfig.h" # include "mitkPPSeqSize.h" # # /* MITK_PP_SEQ_ENUM */ # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_ENUM(seq) MITK_PP_SEQ_ENUM_I(seq) # define MITK_PP_SEQ_ENUM_I(seq) MITK_PP_CAT(MITK_PP_SEQ_ENUM_, MITK_PP_SEQ_SIZE(seq)) seq # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_ENUM(seq) MITK_PP_SEQ_ENUM_I(MITK_PP_SEQ_SIZE(seq), seq) # define MITK_PP_SEQ_ENUM_I(size, seq) MITK_PP_CAT(MITK_PP_SEQ_ENUM_, size) seq # else # define MITK_PP_SEQ_ENUM(seq) MITK_PP_CAT(MITK_PP_SEQ_ENUM_, MITK_PP_SEQ_SIZE(seq)) seq # endif # # define MITK_PP_SEQ_ENUM_1(x) x # define MITK_PP_SEQ_ENUM_2(x) x, MITK_PP_SEQ_ENUM_1 # define MITK_PP_SEQ_ENUM_3(x) x, MITK_PP_SEQ_ENUM_2 # define MITK_PP_SEQ_ENUM_4(x) x, MITK_PP_SEQ_ENUM_3 # define MITK_PP_SEQ_ENUM_5(x) x, MITK_PP_SEQ_ENUM_4 # define MITK_PP_SEQ_ENUM_6(x) x, MITK_PP_SEQ_ENUM_5 # define MITK_PP_SEQ_ENUM_7(x) x, MITK_PP_SEQ_ENUM_6 # define MITK_PP_SEQ_ENUM_8(x) x, MITK_PP_SEQ_ENUM_7 # define MITK_PP_SEQ_ENUM_9(x) x, MITK_PP_SEQ_ENUM_8 # define MITK_PP_SEQ_ENUM_10(x) x, MITK_PP_SEQ_ENUM_9 # define MITK_PP_SEQ_ENUM_11(x) x, MITK_PP_SEQ_ENUM_10 # define MITK_PP_SEQ_ENUM_12(x) x, MITK_PP_SEQ_ENUM_11 # define MITK_PP_SEQ_ENUM_13(x) x, MITK_PP_SEQ_ENUM_12 # define MITK_PP_SEQ_ENUM_14(x) x, MITK_PP_SEQ_ENUM_13 # define MITK_PP_SEQ_ENUM_15(x) x, MITK_PP_SEQ_ENUM_14 # define MITK_PP_SEQ_ENUM_16(x) x, MITK_PP_SEQ_ENUM_15 # define MITK_PP_SEQ_ENUM_17(x) x, MITK_PP_SEQ_ENUM_16 # define MITK_PP_SEQ_ENUM_18(x) x, MITK_PP_SEQ_ENUM_17 # define MITK_PP_SEQ_ENUM_19(x) x, MITK_PP_SEQ_ENUM_18 # define MITK_PP_SEQ_ENUM_20(x) x, MITK_PP_SEQ_ENUM_19 # define MITK_PP_SEQ_ENUM_21(x) x, MITK_PP_SEQ_ENUM_20 # define MITK_PP_SEQ_ENUM_22(x) x, MITK_PP_SEQ_ENUM_21 # define MITK_PP_SEQ_ENUM_23(x) x, MITK_PP_SEQ_ENUM_22 # define MITK_PP_SEQ_ENUM_24(x) x, MITK_PP_SEQ_ENUM_23 # define MITK_PP_SEQ_ENUM_25(x) x, MITK_PP_SEQ_ENUM_24 # define MITK_PP_SEQ_ENUM_26(x) x, MITK_PP_SEQ_ENUM_25 # define MITK_PP_SEQ_ENUM_27(x) x, MITK_PP_SEQ_ENUM_26 # define MITK_PP_SEQ_ENUM_28(x) x, MITK_PP_SEQ_ENUM_27 # define MITK_PP_SEQ_ENUM_29(x) x, MITK_PP_SEQ_ENUM_28 # define MITK_PP_SEQ_ENUM_30(x) x, MITK_PP_SEQ_ENUM_29 # define MITK_PP_SEQ_ENUM_31(x) x, MITK_PP_SEQ_ENUM_30 # define MITK_PP_SEQ_ENUM_32(x) x, MITK_PP_SEQ_ENUM_31 # define MITK_PP_SEQ_ENUM_33(x) x, MITK_PP_SEQ_ENUM_32 # define MITK_PP_SEQ_ENUM_34(x) x, MITK_PP_SEQ_ENUM_33 # define MITK_PP_SEQ_ENUM_35(x) x, MITK_PP_SEQ_ENUM_34 # define MITK_PP_SEQ_ENUM_36(x) x, MITK_PP_SEQ_ENUM_35 # define MITK_PP_SEQ_ENUM_37(x) x, MITK_PP_SEQ_ENUM_36 # define MITK_PP_SEQ_ENUM_38(x) x, MITK_PP_SEQ_ENUM_37 # define MITK_PP_SEQ_ENUM_39(x) x, MITK_PP_SEQ_ENUM_38 # define MITK_PP_SEQ_ENUM_40(x) x, MITK_PP_SEQ_ENUM_39 # define MITK_PP_SEQ_ENUM_41(x) x, MITK_PP_SEQ_ENUM_40 # define MITK_PP_SEQ_ENUM_42(x) x, MITK_PP_SEQ_ENUM_41 # define MITK_PP_SEQ_ENUM_43(x) x, MITK_PP_SEQ_ENUM_42 # define MITK_PP_SEQ_ENUM_44(x) x, MITK_PP_SEQ_ENUM_43 # define MITK_PP_SEQ_ENUM_45(x) x, MITK_PP_SEQ_ENUM_44 # define MITK_PP_SEQ_ENUM_46(x) x, MITK_PP_SEQ_ENUM_45 # define MITK_PP_SEQ_ENUM_47(x) x, MITK_PP_SEQ_ENUM_46 # define MITK_PP_SEQ_ENUM_48(x) x, MITK_PP_SEQ_ENUM_47 # define MITK_PP_SEQ_ENUM_49(x) x, MITK_PP_SEQ_ENUM_48 # define MITK_PP_SEQ_ENUM_50(x) x, MITK_PP_SEQ_ENUM_49 # define MITK_PP_SEQ_ENUM_51(x) x, MITK_PP_SEQ_ENUM_50 # define MITK_PP_SEQ_ENUM_52(x) x, MITK_PP_SEQ_ENUM_51 # define MITK_PP_SEQ_ENUM_53(x) x, MITK_PP_SEQ_ENUM_52 # define MITK_PP_SEQ_ENUM_54(x) x, MITK_PP_SEQ_ENUM_53 # define MITK_PP_SEQ_ENUM_55(x) x, MITK_PP_SEQ_ENUM_54 # define MITK_PP_SEQ_ENUM_56(x) x, MITK_PP_SEQ_ENUM_55 # define MITK_PP_SEQ_ENUM_57(x) x, MITK_PP_SEQ_ENUM_56 # define MITK_PP_SEQ_ENUM_58(x) x, MITK_PP_SEQ_ENUM_57 # define MITK_PP_SEQ_ENUM_59(x) x, MITK_PP_SEQ_ENUM_58 # define MITK_PP_SEQ_ENUM_60(x) x, MITK_PP_SEQ_ENUM_59 # define MITK_PP_SEQ_ENUM_61(x) x, MITK_PP_SEQ_ENUM_60 # define MITK_PP_SEQ_ENUM_62(x) x, MITK_PP_SEQ_ENUM_61 # define MITK_PP_SEQ_ENUM_63(x) x, MITK_PP_SEQ_ENUM_62 # define MITK_PP_SEQ_ENUM_64(x) x, MITK_PP_SEQ_ENUM_63 # define MITK_PP_SEQ_ENUM_65(x) x, MITK_PP_SEQ_ENUM_64 # define MITK_PP_SEQ_ENUM_66(x) x, MITK_PP_SEQ_ENUM_65 # define MITK_PP_SEQ_ENUM_67(x) x, MITK_PP_SEQ_ENUM_66 # define MITK_PP_SEQ_ENUM_68(x) x, MITK_PP_SEQ_ENUM_67 # define MITK_PP_SEQ_ENUM_69(x) x, MITK_PP_SEQ_ENUM_68 # define MITK_PP_SEQ_ENUM_70(x) x, MITK_PP_SEQ_ENUM_69 # define MITK_PP_SEQ_ENUM_71(x) x, MITK_PP_SEQ_ENUM_70 # define MITK_PP_SEQ_ENUM_72(x) x, MITK_PP_SEQ_ENUM_71 # define MITK_PP_SEQ_ENUM_73(x) x, MITK_PP_SEQ_ENUM_72 # define MITK_PP_SEQ_ENUM_74(x) x, MITK_PP_SEQ_ENUM_73 # define MITK_PP_SEQ_ENUM_75(x) x, MITK_PP_SEQ_ENUM_74 # define MITK_PP_SEQ_ENUM_76(x) x, MITK_PP_SEQ_ENUM_75 # define MITK_PP_SEQ_ENUM_77(x) x, MITK_PP_SEQ_ENUM_76 # define MITK_PP_SEQ_ENUM_78(x) x, MITK_PP_SEQ_ENUM_77 # define MITK_PP_SEQ_ENUM_79(x) x, MITK_PP_SEQ_ENUM_78 # define MITK_PP_SEQ_ENUM_80(x) x, MITK_PP_SEQ_ENUM_79 # define MITK_PP_SEQ_ENUM_81(x) x, MITK_PP_SEQ_ENUM_80 # define MITK_PP_SEQ_ENUM_82(x) x, MITK_PP_SEQ_ENUM_81 # define MITK_PP_SEQ_ENUM_83(x) x, MITK_PP_SEQ_ENUM_82 # define MITK_PP_SEQ_ENUM_84(x) x, MITK_PP_SEQ_ENUM_83 # define MITK_PP_SEQ_ENUM_85(x) x, MITK_PP_SEQ_ENUM_84 # define MITK_PP_SEQ_ENUM_86(x) x, MITK_PP_SEQ_ENUM_85 # define MITK_PP_SEQ_ENUM_87(x) x, MITK_PP_SEQ_ENUM_86 # define MITK_PP_SEQ_ENUM_88(x) x, MITK_PP_SEQ_ENUM_87 # define MITK_PP_SEQ_ENUM_89(x) x, MITK_PP_SEQ_ENUM_88 # define MITK_PP_SEQ_ENUM_90(x) x, MITK_PP_SEQ_ENUM_89 # define MITK_PP_SEQ_ENUM_91(x) x, MITK_PP_SEQ_ENUM_90 # define MITK_PP_SEQ_ENUM_92(x) x, MITK_PP_SEQ_ENUM_91 # define MITK_PP_SEQ_ENUM_93(x) x, MITK_PP_SEQ_ENUM_92 # define MITK_PP_SEQ_ENUM_94(x) x, MITK_PP_SEQ_ENUM_93 # define MITK_PP_SEQ_ENUM_95(x) x, MITK_PP_SEQ_ENUM_94 # define MITK_PP_SEQ_ENUM_96(x) x, MITK_PP_SEQ_ENUM_95 # define MITK_PP_SEQ_ENUM_97(x) x, MITK_PP_SEQ_ENUM_96 # define MITK_PP_SEQ_ENUM_98(x) x, MITK_PP_SEQ_ENUM_97 # define MITK_PP_SEQ_ENUM_99(x) x, MITK_PP_SEQ_ENUM_98 # define MITK_PP_SEQ_ENUM_100(x) x, MITK_PP_SEQ_ENUM_99 # define MITK_PP_SEQ_ENUM_101(x) x, MITK_PP_SEQ_ENUM_100 # define MITK_PP_SEQ_ENUM_102(x) x, MITK_PP_SEQ_ENUM_101 # define MITK_PP_SEQ_ENUM_103(x) x, MITK_PP_SEQ_ENUM_102 # define MITK_PP_SEQ_ENUM_104(x) x, MITK_PP_SEQ_ENUM_103 # define MITK_PP_SEQ_ENUM_105(x) x, MITK_PP_SEQ_ENUM_104 # define MITK_PP_SEQ_ENUM_106(x) x, MITK_PP_SEQ_ENUM_105 # define MITK_PP_SEQ_ENUM_107(x) x, MITK_PP_SEQ_ENUM_106 # define MITK_PP_SEQ_ENUM_108(x) x, MITK_PP_SEQ_ENUM_107 # define MITK_PP_SEQ_ENUM_109(x) x, MITK_PP_SEQ_ENUM_108 # define MITK_PP_SEQ_ENUM_110(x) x, MITK_PP_SEQ_ENUM_109 # define MITK_PP_SEQ_ENUM_111(x) x, MITK_PP_SEQ_ENUM_110 # define MITK_PP_SEQ_ENUM_112(x) x, MITK_PP_SEQ_ENUM_111 # define MITK_PP_SEQ_ENUM_113(x) x, MITK_PP_SEQ_ENUM_112 # define MITK_PP_SEQ_ENUM_114(x) x, MITK_PP_SEQ_ENUM_113 # define MITK_PP_SEQ_ENUM_115(x) x, MITK_PP_SEQ_ENUM_114 # define MITK_PP_SEQ_ENUM_116(x) x, MITK_PP_SEQ_ENUM_115 # define MITK_PP_SEQ_ENUM_117(x) x, MITK_PP_SEQ_ENUM_116 # define MITK_PP_SEQ_ENUM_118(x) x, MITK_PP_SEQ_ENUM_117 # define MITK_PP_SEQ_ENUM_119(x) x, MITK_PP_SEQ_ENUM_118 # define MITK_PP_SEQ_ENUM_120(x) x, MITK_PP_SEQ_ENUM_119 # define MITK_PP_SEQ_ENUM_121(x) x, MITK_PP_SEQ_ENUM_120 # define MITK_PP_SEQ_ENUM_122(x) x, MITK_PP_SEQ_ENUM_121 # define MITK_PP_SEQ_ENUM_123(x) x, MITK_PP_SEQ_ENUM_122 # define MITK_PP_SEQ_ENUM_124(x) x, MITK_PP_SEQ_ENUM_123 # define MITK_PP_SEQ_ENUM_125(x) x, MITK_PP_SEQ_ENUM_124 # define MITK_PP_SEQ_ENUM_126(x) x, MITK_PP_SEQ_ENUM_125 # define MITK_PP_SEQ_ENUM_127(x) x, MITK_PP_SEQ_ENUM_126 # define MITK_PP_SEQ_ENUM_128(x) x, MITK_PP_SEQ_ENUM_127 # define MITK_PP_SEQ_ENUM_129(x) x, MITK_PP_SEQ_ENUM_128 # define MITK_PP_SEQ_ENUM_130(x) x, MITK_PP_SEQ_ENUM_129 # define MITK_PP_SEQ_ENUM_131(x) x, MITK_PP_SEQ_ENUM_130 # define MITK_PP_SEQ_ENUM_132(x) x, MITK_PP_SEQ_ENUM_131 # define MITK_PP_SEQ_ENUM_133(x) x, MITK_PP_SEQ_ENUM_132 # define MITK_PP_SEQ_ENUM_134(x) x, MITK_PP_SEQ_ENUM_133 # define MITK_PP_SEQ_ENUM_135(x) x, MITK_PP_SEQ_ENUM_134 # define MITK_PP_SEQ_ENUM_136(x) x, MITK_PP_SEQ_ENUM_135 # define MITK_PP_SEQ_ENUM_137(x) x, MITK_PP_SEQ_ENUM_136 # define MITK_PP_SEQ_ENUM_138(x) x, MITK_PP_SEQ_ENUM_137 # define MITK_PP_SEQ_ENUM_139(x) x, MITK_PP_SEQ_ENUM_138 # define MITK_PP_SEQ_ENUM_140(x) x, MITK_PP_SEQ_ENUM_139 # define MITK_PP_SEQ_ENUM_141(x) x, MITK_PP_SEQ_ENUM_140 # define MITK_PP_SEQ_ENUM_142(x) x, MITK_PP_SEQ_ENUM_141 # define MITK_PP_SEQ_ENUM_143(x) x, MITK_PP_SEQ_ENUM_142 # define MITK_PP_SEQ_ENUM_144(x) x, MITK_PP_SEQ_ENUM_143 # define MITK_PP_SEQ_ENUM_145(x) x, MITK_PP_SEQ_ENUM_144 # define MITK_PP_SEQ_ENUM_146(x) x, MITK_PP_SEQ_ENUM_145 # define MITK_PP_SEQ_ENUM_147(x) x, MITK_PP_SEQ_ENUM_146 # define MITK_PP_SEQ_ENUM_148(x) x, MITK_PP_SEQ_ENUM_147 # define MITK_PP_SEQ_ENUM_149(x) x, MITK_PP_SEQ_ENUM_148 # define MITK_PP_SEQ_ENUM_150(x) x, MITK_PP_SEQ_ENUM_149 # define MITK_PP_SEQ_ENUM_151(x) x, MITK_PP_SEQ_ENUM_150 # define MITK_PP_SEQ_ENUM_152(x) x, MITK_PP_SEQ_ENUM_151 # define MITK_PP_SEQ_ENUM_153(x) x, MITK_PP_SEQ_ENUM_152 # define MITK_PP_SEQ_ENUM_154(x) x, MITK_PP_SEQ_ENUM_153 # define MITK_PP_SEQ_ENUM_155(x) x, MITK_PP_SEQ_ENUM_154 # define MITK_PP_SEQ_ENUM_156(x) x, MITK_PP_SEQ_ENUM_155 # define MITK_PP_SEQ_ENUM_157(x) x, MITK_PP_SEQ_ENUM_156 # define MITK_PP_SEQ_ENUM_158(x) x, MITK_PP_SEQ_ENUM_157 # define MITK_PP_SEQ_ENUM_159(x) x, MITK_PP_SEQ_ENUM_158 # define MITK_PP_SEQ_ENUM_160(x) x, MITK_PP_SEQ_ENUM_159 # define MITK_PP_SEQ_ENUM_161(x) x, MITK_PP_SEQ_ENUM_160 # define MITK_PP_SEQ_ENUM_162(x) x, MITK_PP_SEQ_ENUM_161 # define MITK_PP_SEQ_ENUM_163(x) x, MITK_PP_SEQ_ENUM_162 # define MITK_PP_SEQ_ENUM_164(x) x, MITK_PP_SEQ_ENUM_163 # define MITK_PP_SEQ_ENUM_165(x) x, MITK_PP_SEQ_ENUM_164 # define MITK_PP_SEQ_ENUM_166(x) x, MITK_PP_SEQ_ENUM_165 # define MITK_PP_SEQ_ENUM_167(x) x, MITK_PP_SEQ_ENUM_166 # define MITK_PP_SEQ_ENUM_168(x) x, MITK_PP_SEQ_ENUM_167 # define MITK_PP_SEQ_ENUM_169(x) x, MITK_PP_SEQ_ENUM_168 # define MITK_PP_SEQ_ENUM_170(x) x, MITK_PP_SEQ_ENUM_169 # define MITK_PP_SEQ_ENUM_171(x) x, MITK_PP_SEQ_ENUM_170 # define MITK_PP_SEQ_ENUM_172(x) x, MITK_PP_SEQ_ENUM_171 # define MITK_PP_SEQ_ENUM_173(x) x, MITK_PP_SEQ_ENUM_172 # define MITK_PP_SEQ_ENUM_174(x) x, MITK_PP_SEQ_ENUM_173 # define MITK_PP_SEQ_ENUM_175(x) x, MITK_PP_SEQ_ENUM_174 # define MITK_PP_SEQ_ENUM_176(x) x, MITK_PP_SEQ_ENUM_175 # define MITK_PP_SEQ_ENUM_177(x) x, MITK_PP_SEQ_ENUM_176 # define MITK_PP_SEQ_ENUM_178(x) x, MITK_PP_SEQ_ENUM_177 # define MITK_PP_SEQ_ENUM_179(x) x, MITK_PP_SEQ_ENUM_178 # define MITK_PP_SEQ_ENUM_180(x) x, MITK_PP_SEQ_ENUM_179 # define MITK_PP_SEQ_ENUM_181(x) x, MITK_PP_SEQ_ENUM_180 # define MITK_PP_SEQ_ENUM_182(x) x, MITK_PP_SEQ_ENUM_181 # define MITK_PP_SEQ_ENUM_183(x) x, MITK_PP_SEQ_ENUM_182 # define MITK_PP_SEQ_ENUM_184(x) x, MITK_PP_SEQ_ENUM_183 # define MITK_PP_SEQ_ENUM_185(x) x, MITK_PP_SEQ_ENUM_184 # define MITK_PP_SEQ_ENUM_186(x) x, MITK_PP_SEQ_ENUM_185 # define MITK_PP_SEQ_ENUM_187(x) x, MITK_PP_SEQ_ENUM_186 # define MITK_PP_SEQ_ENUM_188(x) x, MITK_PP_SEQ_ENUM_187 # define MITK_PP_SEQ_ENUM_189(x) x, MITK_PP_SEQ_ENUM_188 # define MITK_PP_SEQ_ENUM_190(x) x, MITK_PP_SEQ_ENUM_189 # define MITK_PP_SEQ_ENUM_191(x) x, MITK_PP_SEQ_ENUM_190 # define MITK_PP_SEQ_ENUM_192(x) x, MITK_PP_SEQ_ENUM_191 # define MITK_PP_SEQ_ENUM_193(x) x, MITK_PP_SEQ_ENUM_192 # define MITK_PP_SEQ_ENUM_194(x) x, MITK_PP_SEQ_ENUM_193 # define MITK_PP_SEQ_ENUM_195(x) x, MITK_PP_SEQ_ENUM_194 # define MITK_PP_SEQ_ENUM_196(x) x, MITK_PP_SEQ_ENUM_195 # define MITK_PP_SEQ_ENUM_197(x) x, MITK_PP_SEQ_ENUM_196 # define MITK_PP_SEQ_ENUM_198(x) x, MITK_PP_SEQ_ENUM_197 # define MITK_PP_SEQ_ENUM_199(x) x, MITK_PP_SEQ_ENUM_198 # define MITK_PP_SEQ_ENUM_200(x) x, MITK_PP_SEQ_ENUM_199 # define MITK_PP_SEQ_ENUM_201(x) x, MITK_PP_SEQ_ENUM_200 # define MITK_PP_SEQ_ENUM_202(x) x, MITK_PP_SEQ_ENUM_201 # define MITK_PP_SEQ_ENUM_203(x) x, MITK_PP_SEQ_ENUM_202 # define MITK_PP_SEQ_ENUM_204(x) x, MITK_PP_SEQ_ENUM_203 # define MITK_PP_SEQ_ENUM_205(x) x, MITK_PP_SEQ_ENUM_204 # define MITK_PP_SEQ_ENUM_206(x) x, MITK_PP_SEQ_ENUM_205 # define MITK_PP_SEQ_ENUM_207(x) x, MITK_PP_SEQ_ENUM_206 # define MITK_PP_SEQ_ENUM_208(x) x, MITK_PP_SEQ_ENUM_207 # define MITK_PP_SEQ_ENUM_209(x) x, MITK_PP_SEQ_ENUM_208 # define MITK_PP_SEQ_ENUM_210(x) x, MITK_PP_SEQ_ENUM_209 # define MITK_PP_SEQ_ENUM_211(x) x, MITK_PP_SEQ_ENUM_210 # define MITK_PP_SEQ_ENUM_212(x) x, MITK_PP_SEQ_ENUM_211 # define MITK_PP_SEQ_ENUM_213(x) x, MITK_PP_SEQ_ENUM_212 # define MITK_PP_SEQ_ENUM_214(x) x, MITK_PP_SEQ_ENUM_213 # define MITK_PP_SEQ_ENUM_215(x) x, MITK_PP_SEQ_ENUM_214 # define MITK_PP_SEQ_ENUM_216(x) x, MITK_PP_SEQ_ENUM_215 # define MITK_PP_SEQ_ENUM_217(x) x, MITK_PP_SEQ_ENUM_216 # define MITK_PP_SEQ_ENUM_218(x) x, MITK_PP_SEQ_ENUM_217 # define MITK_PP_SEQ_ENUM_219(x) x, MITK_PP_SEQ_ENUM_218 # define MITK_PP_SEQ_ENUM_220(x) x, MITK_PP_SEQ_ENUM_219 # define MITK_PP_SEQ_ENUM_221(x) x, MITK_PP_SEQ_ENUM_220 # define MITK_PP_SEQ_ENUM_222(x) x, MITK_PP_SEQ_ENUM_221 # define MITK_PP_SEQ_ENUM_223(x) x, MITK_PP_SEQ_ENUM_222 # define MITK_PP_SEQ_ENUM_224(x) x, MITK_PP_SEQ_ENUM_223 # define MITK_PP_SEQ_ENUM_225(x) x, MITK_PP_SEQ_ENUM_224 # define MITK_PP_SEQ_ENUM_226(x) x, MITK_PP_SEQ_ENUM_225 # define MITK_PP_SEQ_ENUM_227(x) x, MITK_PP_SEQ_ENUM_226 # define MITK_PP_SEQ_ENUM_228(x) x, MITK_PP_SEQ_ENUM_227 # define MITK_PP_SEQ_ENUM_229(x) x, MITK_PP_SEQ_ENUM_228 # define MITK_PP_SEQ_ENUM_230(x) x, MITK_PP_SEQ_ENUM_229 # define MITK_PP_SEQ_ENUM_231(x) x, MITK_PP_SEQ_ENUM_230 # define MITK_PP_SEQ_ENUM_232(x) x, MITK_PP_SEQ_ENUM_231 # define MITK_PP_SEQ_ENUM_233(x) x, MITK_PP_SEQ_ENUM_232 # define MITK_PP_SEQ_ENUM_234(x) x, MITK_PP_SEQ_ENUM_233 # define MITK_PP_SEQ_ENUM_235(x) x, MITK_PP_SEQ_ENUM_234 # define MITK_PP_SEQ_ENUM_236(x) x, MITK_PP_SEQ_ENUM_235 # define MITK_PP_SEQ_ENUM_237(x) x, MITK_PP_SEQ_ENUM_236 # define MITK_PP_SEQ_ENUM_238(x) x, MITK_PP_SEQ_ENUM_237 # define MITK_PP_SEQ_ENUM_239(x) x, MITK_PP_SEQ_ENUM_238 # define MITK_PP_SEQ_ENUM_240(x) x, MITK_PP_SEQ_ENUM_239 # define MITK_PP_SEQ_ENUM_241(x) x, MITK_PP_SEQ_ENUM_240 # define MITK_PP_SEQ_ENUM_242(x) x, MITK_PP_SEQ_ENUM_241 # define MITK_PP_SEQ_ENUM_243(x) x, MITK_PP_SEQ_ENUM_242 # define MITK_PP_SEQ_ENUM_244(x) x, MITK_PP_SEQ_ENUM_243 # define MITK_PP_SEQ_ENUM_245(x) x, MITK_PP_SEQ_ENUM_244 # define MITK_PP_SEQ_ENUM_246(x) x, MITK_PP_SEQ_ENUM_245 # define MITK_PP_SEQ_ENUM_247(x) x, MITK_PP_SEQ_ENUM_246 # define MITK_PP_SEQ_ENUM_248(x) x, MITK_PP_SEQ_ENUM_247 # define MITK_PP_SEQ_ENUM_249(x) x, MITK_PP_SEQ_ENUM_248 # define MITK_PP_SEQ_ENUM_250(x) x, MITK_PP_SEQ_ENUM_249 # define MITK_PP_SEQ_ENUM_251(x) x, MITK_PP_SEQ_ENUM_250 # define MITK_PP_SEQ_ENUM_252(x) x, MITK_PP_SEQ_ENUM_251 # define MITK_PP_SEQ_ENUM_253(x) x, MITK_PP_SEQ_ENUM_252 # define MITK_PP_SEQ_ENUM_254(x) x, MITK_PP_SEQ_ENUM_253 # define MITK_PP_SEQ_ENUM_255(x) x, MITK_PP_SEQ_ENUM_254 # define MITK_PP_SEQ_ENUM_256(x) x, MITK_PP_SEQ_ENUM_255 # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqForEach.h b/Core/Code/Algorithms/mitkPPSeqForEach.h index 21b9b19aae..901c0cb9ac 100644 --- a/Core/Code/Algorithms/mitkPPSeqForEach.h +++ b/Core/Code/Algorithms/mitkPPSeqForEach.h @@ -1,60 +1,75 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_FOR_EACH_HPP # define MITK_PREPROCESSOR_SEQ_FOR_EACH_HPP # # include "mitkPPArithmeticDec.h" # include "mitkPPConfig.h" # include "mitkPPRepetitionFor.h" # include "mitkPPSeq.h" # include "mitkPPSeqSize.h" # include "mitkPPTupleElem.h" # include "mitkPPTupleRem.h" # # /* MITK_PP_SEQ_FOR_EACH */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_FOR_EACH(macro, data, seq) MITK_PP_FOR((macro, data, seq (nil)), MITK_PP_SEQ_FOR_EACH_P, MITK_PP_SEQ_FOR_EACH_O, MITK_PP_SEQ_FOR_EACH_M) # else # define MITK_PP_SEQ_FOR_EACH(macro, data, seq) MITK_PP_SEQ_FOR_EACH_D(macro, data, seq) # define MITK_PP_SEQ_FOR_EACH_D(macro, data, seq) MITK_PP_FOR((macro, data, seq (nil)), MITK_PP_SEQ_FOR_EACH_P, MITK_PP_SEQ_FOR_EACH_O, MITK_PP_SEQ_FOR_EACH_M) # endif # # define MITK_PP_SEQ_FOR_EACH_P(r, x) MITK_PP_DEC(MITK_PP_SEQ_SIZE(MITK_PP_TUPLE_ELEM(3, 2, x))) # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_STRICT() # define MITK_PP_SEQ_FOR_EACH_O(r, x) MITK_PP_SEQ_FOR_EACH_O_I x # else # define MITK_PP_SEQ_FOR_EACH_O(r, x) MITK_PP_SEQ_FOR_EACH_O_I(MITK_PP_TUPLE_ELEM(3, 0, x), MITK_PP_TUPLE_ELEM(3, 1, x), MITK_PP_TUPLE_ELEM(3, 2, x)) # endif # # define MITK_PP_SEQ_FOR_EACH_O_I(macro, data, seq) (macro, data, MITK_PP_SEQ_TAIL(seq)) # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_STRICT() # define MITK_PP_SEQ_FOR_EACH_M(r, x) MITK_PP_SEQ_FOR_EACH_M_IM(r, MITK_PP_TUPLE_REM_3 x) # define MITK_PP_SEQ_FOR_EACH_M_IM(r, im) MITK_PP_SEQ_FOR_EACH_M_I(r, im) # else # define MITK_PP_SEQ_FOR_EACH_M(r, x) MITK_PP_SEQ_FOR_EACH_M_I(r, MITK_PP_TUPLE_ELEM(3, 0, x), MITK_PP_TUPLE_ELEM(3, 1, x), MITK_PP_TUPLE_ELEM(3, 2, x)) # endif # # define MITK_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, MITK_PP_SEQ_HEAD(seq)) # # /* MITK_PP_SEQ_FOR_EACH_R */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_FOR_EACH_R(r, macro, data, seq) MITK_PP_FOR_ ## r((macro, data, seq (nil)), MITK_PP_SEQ_FOR_EACH_P, MITK_PP_SEQ_FOR_EACH_O, MITK_PP_SEQ_FOR_EACH_M) # else # define MITK_PP_SEQ_FOR_EACH_R(r, macro, data, seq) MITK_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) # define MITK_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) MITK_PP_FOR_ ## r((macro, data, seq (nil)), MITK_PP_SEQ_FOR_EACH_P, MITK_PP_SEQ_FOR_EACH_O, MITK_PP_SEQ_FOR_EACH_M) # endif # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqForEachProduct.h b/Core/Code/Algorithms/mitkPPSeqForEachProduct.h index 29eebaca94..175fc25da9 100644 --- a/Core/Code/Algorithms/mitkPPSeqForEachProduct.h +++ b/Core/Code/Algorithms/mitkPPSeqForEachProduct.h @@ -1,126 +1,141 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_FOR_EACH_PRODUCT_HPP # define MITK_PREPROCESSOR_SEQ_FOR_EACH_PRODUCT_HPP # # include "mitkPPArithmeticDec.h" # include "mitkPPConfig.h" # include "mitkPPControlIf.h" # include "mitkPPRepetitionFor.h" # include "mitkPPSeq.h" # include "mitkPPSeqSize.h" # include "mitkPPTupleElem.h" # include "mitkPPTupleRem.h" # # /* MITK_PP_SEQ_FOR_EACH_PRODUCT */ # # define MITK_PP_SEQ_FOR_EACH_PRODUCT(macro, sets) MITK_PP_SEQ_FOR_EACH_PRODUCT_E(MITK_PP_FOR, macro, sets) # # /* MITK_PP_SEQ_FOR_EACH_PRODUCT_R */ # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_R(r, macro, sets) MITK_PP_SEQ_FOR_EACH_PRODUCT_E(MITK_PP_FOR_ ## r, macro, sets) # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_FOR_EACH_PRODUCT_E(impl, macro, sets) impl((MITK_PP_SEQ_HEAD(sets)(nil), MITK_PP_SEQ_TAIL(sets)(nil), (nil), macro), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_0) # else # define MITK_PP_SEQ_FOR_EACH_PRODUCT_E(impl, macro, sets) MITK_PP_SEQ_FOR_EACH_PRODUCT_E_I(impl, macro, sets) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_E_I(impl, macro, sets) impl((MITK_PP_SEQ_HEAD(sets)(nil), MITK_PP_SEQ_TAIL(sets)(nil), (nil), macro), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_0) # endif # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_STRICT() # define MITK_PP_SEQ_FOR_EACH_PRODUCT_P(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_P_I data # define MITK_PP_SEQ_FOR_EACH_PRODUCT_P_I(cset, rset, res, macro) MITK_PP_DEC(MITK_PP_SEQ_SIZE(cset)) # else # define MITK_PP_SEQ_FOR_EACH_PRODUCT_P(r, data) MITK_PP_DEC(MITK_PP_SEQ_SIZE(MITK_PP_TUPLE_ELEM(4, 0, data))) # endif # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_FOR_EACH_PRODUCT_O(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_O_I data # define MITK_PP_SEQ_FOR_EACH_PRODUCT_O_I(cset, rset, res, macro) (MITK_PP_SEQ_TAIL(cset), rset, res, macro) # else # define MITK_PP_SEQ_FOR_EACH_PRODUCT_O(r, data) (MITK_PP_SEQ_TAIL(MITK_PP_TUPLE_ELEM(4, 0, data)), MITK_PP_TUPLE_ELEM(4, 1, data), MITK_PP_TUPLE_ELEM(4, 2, data), MITK_PP_TUPLE_ELEM(4, 3, data)) # endif # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, i) MITK_PP_IF(MITK_PP_DEC(MITK_PP_SEQ_SIZE(MITK_PP_TUPLE_ELEM(4, 1, data))), MITK_PP_SEQ_FOR_EACH_PRODUCT_N_ ## i, MITK_PP_SEQ_FOR_EACH_PRODUCT_I) # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_FOR_EACH_PRODUCT_I(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_I_I(r, MITK_PP_TUPLE_ELEM(4, 0, data), MITK_PP_TUPLE_ELEM(4, 1, data), MITK_PP_TUPLE_ELEM(4, 2, data), MITK_PP_TUPLE_ELEM(4, 3, data)) # else # define MITK_PP_SEQ_FOR_EACH_PRODUCT_I(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_I_IM(r, MITK_PP_TUPLE_REM_4 data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_I_IM(r, im) MITK_PP_SEQ_FOR_EACH_PRODUCT_I_I(r, im) # endif # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_I_I(r, cset, rset, res, macro) macro(r, MITK_PP_SEQ_TAIL(res (MITK_PP_SEQ_HEAD(cset)))) # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data) MITK_PP_SEQ_FOR_EACH_PRODUCT_H_I data # else # define MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data) MITK_PP_SEQ_FOR_EACH_PRODUCT_H_I(MITK_PP_TUPLE_ELEM(4, 0, data), MITK_PP_TUPLE_ELEM(4, 1, data), MITK_PP_TUPLE_ELEM(4, 2, data), MITK_PP_TUPLE_ELEM(4, 3, data)) # endif # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_H_I(cset, rset, res, macro) (MITK_PP_SEQ_HEAD(rset)(nil), MITK_PP_SEQ_TAIL(rset), res (MITK_PP_SEQ_HEAD(cset)), macro) # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_0(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 0)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_1(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 1)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_2(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 2)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_3(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 3)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_4(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 4)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_5(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 5)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_6(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 6)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_7(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 7)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_8(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 8)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_9(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 9)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_10(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 10)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_11(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 11)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_12(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 12)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_13(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 13)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_14(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 14)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_15(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 15)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_16(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 16)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_17(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 17)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_18(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 18)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_19(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 19)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_20(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 20)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_21(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 21)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_22(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 22)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_23(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 23)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_24(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 24)(r, data) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_M_25(r, data) MITK_PP_SEQ_FOR_EACH_PRODUCT_C(data, 25)(r, data) # # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_0(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_1) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_1(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_2) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_2(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_3) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_3(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_4) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_4(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_5) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_5(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_6) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_6(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_7) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_7(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_8) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_8(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_9) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_9(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_10) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_10(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_11) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_11(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_12) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_12(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_13) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_13(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_14) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_14(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_15) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_15(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_16) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_16(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_17) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_17(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_18) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_18(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_19) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_19(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_20) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_20(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_21) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_21(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_22) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_22(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_23) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_23(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_24) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_24(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_25) # define MITK_PP_SEQ_FOR_EACH_PRODUCT_N_25(r, data) MITK_PP_FOR_ ## r(MITK_PP_SEQ_FOR_EACH_PRODUCT_H(data), MITK_PP_SEQ_FOR_EACH_PRODUCT_P, MITK_PP_SEQ_FOR_EACH_PRODUCT_O, MITK_PP_SEQ_FOR_EACH_PRODUCT_M_26) # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqSize.h b/Core/Code/Algorithms/mitkPPSeqSize.h index 1941d5b57f..28b48d8fa9 100644 --- a/Core/Code/Algorithms/mitkPPSeqSize.h +++ b/Core/Code/Algorithms/mitkPPSeqSize.h @@ -1,548 +1,563 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_SIZE_HPP # define MITK_PREPROCESSOR_SEQ_SIZE_HPP # # include "mitkPPCat.h" # include "mitkPPConfig.h" # include "mitkPPTupleEat.h" # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_SEQ_SIZE(seq) MITK_PP_SEQ_SIZE_I((seq)) # define MITK_PP_SEQ_SIZE_I(par) MITK_PP_SEQ_SIZE_II ## par # define MITK_PP_SEQ_SIZE_II(seq) MITK_PP_CAT(MITK_PP_SEQ_SIZE_, MITK_PP_SEQ_SIZE_0 ## seq) # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() || MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_SEQ_SIZE(seq) MITK_PP_SEQ_SIZE_I(seq) # define MITK_PP_SEQ_SIZE_I(seq) MITK_PP_CAT(MITK_PP_SEQ_SIZE_, MITK_PP_SEQ_SIZE_0 seq) # elif defined(__IBMC__) || defined(__IBMCPP__) # define MITK_PP_SEQ_SIZE(seq) MITK_PP_CAT(MITK_PP_SEQ_SIZE_, MITK_PP_CAT(MITK_PP_SEQ_SIZE_0, seq)) # else # define MITK_PP_SEQ_SIZE(seq) MITK_PP_CAT(MITK_PP_SEQ_SIZE_, MITK_PP_SEQ_SIZE_0 seq) # endif # # define MITK_PP_SEQ_SIZE_0(_) MITK_PP_SEQ_SIZE_1 # define MITK_PP_SEQ_SIZE_1(_) MITK_PP_SEQ_SIZE_2 # define MITK_PP_SEQ_SIZE_2(_) MITK_PP_SEQ_SIZE_3 # define MITK_PP_SEQ_SIZE_3(_) MITK_PP_SEQ_SIZE_4 # define MITK_PP_SEQ_SIZE_4(_) MITK_PP_SEQ_SIZE_5 # define MITK_PP_SEQ_SIZE_5(_) MITK_PP_SEQ_SIZE_6 # define MITK_PP_SEQ_SIZE_6(_) MITK_PP_SEQ_SIZE_7 # define MITK_PP_SEQ_SIZE_7(_) MITK_PP_SEQ_SIZE_8 # define MITK_PP_SEQ_SIZE_8(_) MITK_PP_SEQ_SIZE_9 # define MITK_PP_SEQ_SIZE_9(_) MITK_PP_SEQ_SIZE_10 # define MITK_PP_SEQ_SIZE_10(_) MITK_PP_SEQ_SIZE_11 # define MITK_PP_SEQ_SIZE_11(_) MITK_PP_SEQ_SIZE_12 # define MITK_PP_SEQ_SIZE_12(_) MITK_PP_SEQ_SIZE_13 # define MITK_PP_SEQ_SIZE_13(_) MITK_PP_SEQ_SIZE_14 # define MITK_PP_SEQ_SIZE_14(_) MITK_PP_SEQ_SIZE_15 # define MITK_PP_SEQ_SIZE_15(_) MITK_PP_SEQ_SIZE_16 # define MITK_PP_SEQ_SIZE_16(_) MITK_PP_SEQ_SIZE_17 # define MITK_PP_SEQ_SIZE_17(_) MITK_PP_SEQ_SIZE_18 # define MITK_PP_SEQ_SIZE_18(_) MITK_PP_SEQ_SIZE_19 # define MITK_PP_SEQ_SIZE_19(_) MITK_PP_SEQ_SIZE_20 # define MITK_PP_SEQ_SIZE_20(_) MITK_PP_SEQ_SIZE_21 # define MITK_PP_SEQ_SIZE_21(_) MITK_PP_SEQ_SIZE_22 # define MITK_PP_SEQ_SIZE_22(_) MITK_PP_SEQ_SIZE_23 # define MITK_PP_SEQ_SIZE_23(_) MITK_PP_SEQ_SIZE_24 # define MITK_PP_SEQ_SIZE_24(_) MITK_PP_SEQ_SIZE_25 # define MITK_PP_SEQ_SIZE_25(_) MITK_PP_SEQ_SIZE_26 # define MITK_PP_SEQ_SIZE_26(_) MITK_PP_SEQ_SIZE_27 # define MITK_PP_SEQ_SIZE_27(_) MITK_PP_SEQ_SIZE_28 # define MITK_PP_SEQ_SIZE_28(_) MITK_PP_SEQ_SIZE_29 # define MITK_PP_SEQ_SIZE_29(_) MITK_PP_SEQ_SIZE_30 # define MITK_PP_SEQ_SIZE_30(_) MITK_PP_SEQ_SIZE_31 # define MITK_PP_SEQ_SIZE_31(_) MITK_PP_SEQ_SIZE_32 # define MITK_PP_SEQ_SIZE_32(_) MITK_PP_SEQ_SIZE_33 # define MITK_PP_SEQ_SIZE_33(_) MITK_PP_SEQ_SIZE_34 # define MITK_PP_SEQ_SIZE_34(_) MITK_PP_SEQ_SIZE_35 # define MITK_PP_SEQ_SIZE_35(_) MITK_PP_SEQ_SIZE_36 # define MITK_PP_SEQ_SIZE_36(_) MITK_PP_SEQ_SIZE_37 # define MITK_PP_SEQ_SIZE_37(_) MITK_PP_SEQ_SIZE_38 # define MITK_PP_SEQ_SIZE_38(_) MITK_PP_SEQ_SIZE_39 # define MITK_PP_SEQ_SIZE_39(_) MITK_PP_SEQ_SIZE_40 # define MITK_PP_SEQ_SIZE_40(_) MITK_PP_SEQ_SIZE_41 # define MITK_PP_SEQ_SIZE_41(_) MITK_PP_SEQ_SIZE_42 # define MITK_PP_SEQ_SIZE_42(_) MITK_PP_SEQ_SIZE_43 # define MITK_PP_SEQ_SIZE_43(_) MITK_PP_SEQ_SIZE_44 # define MITK_PP_SEQ_SIZE_44(_) MITK_PP_SEQ_SIZE_45 # define MITK_PP_SEQ_SIZE_45(_) MITK_PP_SEQ_SIZE_46 # define MITK_PP_SEQ_SIZE_46(_) MITK_PP_SEQ_SIZE_47 # define MITK_PP_SEQ_SIZE_47(_) MITK_PP_SEQ_SIZE_48 # define MITK_PP_SEQ_SIZE_48(_) MITK_PP_SEQ_SIZE_49 # define MITK_PP_SEQ_SIZE_49(_) MITK_PP_SEQ_SIZE_50 # define MITK_PP_SEQ_SIZE_50(_) MITK_PP_SEQ_SIZE_51 # define MITK_PP_SEQ_SIZE_51(_) MITK_PP_SEQ_SIZE_52 # define MITK_PP_SEQ_SIZE_52(_) MITK_PP_SEQ_SIZE_53 # define MITK_PP_SEQ_SIZE_53(_) MITK_PP_SEQ_SIZE_54 # define MITK_PP_SEQ_SIZE_54(_) MITK_PP_SEQ_SIZE_55 # define MITK_PP_SEQ_SIZE_55(_) MITK_PP_SEQ_SIZE_56 # define MITK_PP_SEQ_SIZE_56(_) MITK_PP_SEQ_SIZE_57 # define MITK_PP_SEQ_SIZE_57(_) MITK_PP_SEQ_SIZE_58 # define MITK_PP_SEQ_SIZE_58(_) MITK_PP_SEQ_SIZE_59 # define MITK_PP_SEQ_SIZE_59(_) MITK_PP_SEQ_SIZE_60 # define MITK_PP_SEQ_SIZE_60(_) MITK_PP_SEQ_SIZE_61 # define MITK_PP_SEQ_SIZE_61(_) MITK_PP_SEQ_SIZE_62 # define MITK_PP_SEQ_SIZE_62(_) MITK_PP_SEQ_SIZE_63 # define MITK_PP_SEQ_SIZE_63(_) MITK_PP_SEQ_SIZE_64 # define MITK_PP_SEQ_SIZE_64(_) MITK_PP_SEQ_SIZE_65 # define MITK_PP_SEQ_SIZE_65(_) MITK_PP_SEQ_SIZE_66 # define MITK_PP_SEQ_SIZE_66(_) MITK_PP_SEQ_SIZE_67 # define MITK_PP_SEQ_SIZE_67(_) MITK_PP_SEQ_SIZE_68 # define MITK_PP_SEQ_SIZE_68(_) MITK_PP_SEQ_SIZE_69 # define MITK_PP_SEQ_SIZE_69(_) MITK_PP_SEQ_SIZE_70 # define MITK_PP_SEQ_SIZE_70(_) MITK_PP_SEQ_SIZE_71 # define MITK_PP_SEQ_SIZE_71(_) MITK_PP_SEQ_SIZE_72 # define MITK_PP_SEQ_SIZE_72(_) MITK_PP_SEQ_SIZE_73 # define MITK_PP_SEQ_SIZE_73(_) MITK_PP_SEQ_SIZE_74 # define MITK_PP_SEQ_SIZE_74(_) MITK_PP_SEQ_SIZE_75 # define MITK_PP_SEQ_SIZE_75(_) MITK_PP_SEQ_SIZE_76 # define MITK_PP_SEQ_SIZE_76(_) MITK_PP_SEQ_SIZE_77 # define MITK_PP_SEQ_SIZE_77(_) MITK_PP_SEQ_SIZE_78 # define MITK_PP_SEQ_SIZE_78(_) MITK_PP_SEQ_SIZE_79 # define MITK_PP_SEQ_SIZE_79(_) MITK_PP_SEQ_SIZE_80 # define MITK_PP_SEQ_SIZE_80(_) MITK_PP_SEQ_SIZE_81 # define MITK_PP_SEQ_SIZE_81(_) MITK_PP_SEQ_SIZE_82 # define MITK_PP_SEQ_SIZE_82(_) MITK_PP_SEQ_SIZE_83 # define MITK_PP_SEQ_SIZE_83(_) MITK_PP_SEQ_SIZE_84 # define MITK_PP_SEQ_SIZE_84(_) MITK_PP_SEQ_SIZE_85 # define MITK_PP_SEQ_SIZE_85(_) MITK_PP_SEQ_SIZE_86 # define MITK_PP_SEQ_SIZE_86(_) MITK_PP_SEQ_SIZE_87 # define MITK_PP_SEQ_SIZE_87(_) MITK_PP_SEQ_SIZE_88 # define MITK_PP_SEQ_SIZE_88(_) MITK_PP_SEQ_SIZE_89 # define MITK_PP_SEQ_SIZE_89(_) MITK_PP_SEQ_SIZE_90 # define MITK_PP_SEQ_SIZE_90(_) MITK_PP_SEQ_SIZE_91 # define MITK_PP_SEQ_SIZE_91(_) MITK_PP_SEQ_SIZE_92 # define MITK_PP_SEQ_SIZE_92(_) MITK_PP_SEQ_SIZE_93 # define MITK_PP_SEQ_SIZE_93(_) MITK_PP_SEQ_SIZE_94 # define MITK_PP_SEQ_SIZE_94(_) MITK_PP_SEQ_SIZE_95 # define MITK_PP_SEQ_SIZE_95(_) MITK_PP_SEQ_SIZE_96 # define MITK_PP_SEQ_SIZE_96(_) MITK_PP_SEQ_SIZE_97 # define MITK_PP_SEQ_SIZE_97(_) MITK_PP_SEQ_SIZE_98 # define MITK_PP_SEQ_SIZE_98(_) MITK_PP_SEQ_SIZE_99 # define MITK_PP_SEQ_SIZE_99(_) MITK_PP_SEQ_SIZE_100 # define MITK_PP_SEQ_SIZE_100(_) MITK_PP_SEQ_SIZE_101 # define MITK_PP_SEQ_SIZE_101(_) MITK_PP_SEQ_SIZE_102 # define MITK_PP_SEQ_SIZE_102(_) MITK_PP_SEQ_SIZE_103 # define MITK_PP_SEQ_SIZE_103(_) MITK_PP_SEQ_SIZE_104 # define MITK_PP_SEQ_SIZE_104(_) MITK_PP_SEQ_SIZE_105 # define MITK_PP_SEQ_SIZE_105(_) MITK_PP_SEQ_SIZE_106 # define MITK_PP_SEQ_SIZE_106(_) MITK_PP_SEQ_SIZE_107 # define MITK_PP_SEQ_SIZE_107(_) MITK_PP_SEQ_SIZE_108 # define MITK_PP_SEQ_SIZE_108(_) MITK_PP_SEQ_SIZE_109 # define MITK_PP_SEQ_SIZE_109(_) MITK_PP_SEQ_SIZE_110 # define MITK_PP_SEQ_SIZE_110(_) MITK_PP_SEQ_SIZE_111 # define MITK_PP_SEQ_SIZE_111(_) MITK_PP_SEQ_SIZE_112 # define MITK_PP_SEQ_SIZE_112(_) MITK_PP_SEQ_SIZE_113 # define MITK_PP_SEQ_SIZE_113(_) MITK_PP_SEQ_SIZE_114 # define MITK_PP_SEQ_SIZE_114(_) MITK_PP_SEQ_SIZE_115 # define MITK_PP_SEQ_SIZE_115(_) MITK_PP_SEQ_SIZE_116 # define MITK_PP_SEQ_SIZE_116(_) MITK_PP_SEQ_SIZE_117 # define MITK_PP_SEQ_SIZE_117(_) MITK_PP_SEQ_SIZE_118 # define MITK_PP_SEQ_SIZE_118(_) MITK_PP_SEQ_SIZE_119 # define MITK_PP_SEQ_SIZE_119(_) MITK_PP_SEQ_SIZE_120 # define MITK_PP_SEQ_SIZE_120(_) MITK_PP_SEQ_SIZE_121 # define MITK_PP_SEQ_SIZE_121(_) MITK_PP_SEQ_SIZE_122 # define MITK_PP_SEQ_SIZE_122(_) MITK_PP_SEQ_SIZE_123 # define MITK_PP_SEQ_SIZE_123(_) MITK_PP_SEQ_SIZE_124 # define MITK_PP_SEQ_SIZE_124(_) MITK_PP_SEQ_SIZE_125 # define MITK_PP_SEQ_SIZE_125(_) MITK_PP_SEQ_SIZE_126 # define MITK_PP_SEQ_SIZE_126(_) MITK_PP_SEQ_SIZE_127 # define MITK_PP_SEQ_SIZE_127(_) MITK_PP_SEQ_SIZE_128 # define MITK_PP_SEQ_SIZE_128(_) MITK_PP_SEQ_SIZE_129 # define MITK_PP_SEQ_SIZE_129(_) MITK_PP_SEQ_SIZE_130 # define MITK_PP_SEQ_SIZE_130(_) MITK_PP_SEQ_SIZE_131 # define MITK_PP_SEQ_SIZE_131(_) MITK_PP_SEQ_SIZE_132 # define MITK_PP_SEQ_SIZE_132(_) MITK_PP_SEQ_SIZE_133 # define MITK_PP_SEQ_SIZE_133(_) MITK_PP_SEQ_SIZE_134 # define MITK_PP_SEQ_SIZE_134(_) MITK_PP_SEQ_SIZE_135 # define MITK_PP_SEQ_SIZE_135(_) MITK_PP_SEQ_SIZE_136 # define MITK_PP_SEQ_SIZE_136(_) MITK_PP_SEQ_SIZE_137 # define MITK_PP_SEQ_SIZE_137(_) MITK_PP_SEQ_SIZE_138 # define MITK_PP_SEQ_SIZE_138(_) MITK_PP_SEQ_SIZE_139 # define MITK_PP_SEQ_SIZE_139(_) MITK_PP_SEQ_SIZE_140 # define MITK_PP_SEQ_SIZE_140(_) MITK_PP_SEQ_SIZE_141 # define MITK_PP_SEQ_SIZE_141(_) MITK_PP_SEQ_SIZE_142 # define MITK_PP_SEQ_SIZE_142(_) MITK_PP_SEQ_SIZE_143 # define MITK_PP_SEQ_SIZE_143(_) MITK_PP_SEQ_SIZE_144 # define MITK_PP_SEQ_SIZE_144(_) MITK_PP_SEQ_SIZE_145 # define MITK_PP_SEQ_SIZE_145(_) MITK_PP_SEQ_SIZE_146 # define MITK_PP_SEQ_SIZE_146(_) MITK_PP_SEQ_SIZE_147 # define MITK_PP_SEQ_SIZE_147(_) MITK_PP_SEQ_SIZE_148 # define MITK_PP_SEQ_SIZE_148(_) MITK_PP_SEQ_SIZE_149 # define MITK_PP_SEQ_SIZE_149(_) MITK_PP_SEQ_SIZE_150 # define MITK_PP_SEQ_SIZE_150(_) MITK_PP_SEQ_SIZE_151 # define MITK_PP_SEQ_SIZE_151(_) MITK_PP_SEQ_SIZE_152 # define MITK_PP_SEQ_SIZE_152(_) MITK_PP_SEQ_SIZE_153 # define MITK_PP_SEQ_SIZE_153(_) MITK_PP_SEQ_SIZE_154 # define MITK_PP_SEQ_SIZE_154(_) MITK_PP_SEQ_SIZE_155 # define MITK_PP_SEQ_SIZE_155(_) MITK_PP_SEQ_SIZE_156 # define MITK_PP_SEQ_SIZE_156(_) MITK_PP_SEQ_SIZE_157 # define MITK_PP_SEQ_SIZE_157(_) MITK_PP_SEQ_SIZE_158 # define MITK_PP_SEQ_SIZE_158(_) MITK_PP_SEQ_SIZE_159 # define MITK_PP_SEQ_SIZE_159(_) MITK_PP_SEQ_SIZE_160 # define MITK_PP_SEQ_SIZE_160(_) MITK_PP_SEQ_SIZE_161 # define MITK_PP_SEQ_SIZE_161(_) MITK_PP_SEQ_SIZE_162 # define MITK_PP_SEQ_SIZE_162(_) MITK_PP_SEQ_SIZE_163 # define MITK_PP_SEQ_SIZE_163(_) MITK_PP_SEQ_SIZE_164 # define MITK_PP_SEQ_SIZE_164(_) MITK_PP_SEQ_SIZE_165 # define MITK_PP_SEQ_SIZE_165(_) MITK_PP_SEQ_SIZE_166 # define MITK_PP_SEQ_SIZE_166(_) MITK_PP_SEQ_SIZE_167 # define MITK_PP_SEQ_SIZE_167(_) MITK_PP_SEQ_SIZE_168 # define MITK_PP_SEQ_SIZE_168(_) MITK_PP_SEQ_SIZE_169 # define MITK_PP_SEQ_SIZE_169(_) MITK_PP_SEQ_SIZE_170 # define MITK_PP_SEQ_SIZE_170(_) MITK_PP_SEQ_SIZE_171 # define MITK_PP_SEQ_SIZE_171(_) MITK_PP_SEQ_SIZE_172 # define MITK_PP_SEQ_SIZE_172(_) MITK_PP_SEQ_SIZE_173 # define MITK_PP_SEQ_SIZE_173(_) MITK_PP_SEQ_SIZE_174 # define MITK_PP_SEQ_SIZE_174(_) MITK_PP_SEQ_SIZE_175 # define MITK_PP_SEQ_SIZE_175(_) MITK_PP_SEQ_SIZE_176 # define MITK_PP_SEQ_SIZE_176(_) MITK_PP_SEQ_SIZE_177 # define MITK_PP_SEQ_SIZE_177(_) MITK_PP_SEQ_SIZE_178 # define MITK_PP_SEQ_SIZE_178(_) MITK_PP_SEQ_SIZE_179 # define MITK_PP_SEQ_SIZE_179(_) MITK_PP_SEQ_SIZE_180 # define MITK_PP_SEQ_SIZE_180(_) MITK_PP_SEQ_SIZE_181 # define MITK_PP_SEQ_SIZE_181(_) MITK_PP_SEQ_SIZE_182 # define MITK_PP_SEQ_SIZE_182(_) MITK_PP_SEQ_SIZE_183 # define MITK_PP_SEQ_SIZE_183(_) MITK_PP_SEQ_SIZE_184 # define MITK_PP_SEQ_SIZE_184(_) MITK_PP_SEQ_SIZE_185 # define MITK_PP_SEQ_SIZE_185(_) MITK_PP_SEQ_SIZE_186 # define MITK_PP_SEQ_SIZE_186(_) MITK_PP_SEQ_SIZE_187 # define MITK_PP_SEQ_SIZE_187(_) MITK_PP_SEQ_SIZE_188 # define MITK_PP_SEQ_SIZE_188(_) MITK_PP_SEQ_SIZE_189 # define MITK_PP_SEQ_SIZE_189(_) MITK_PP_SEQ_SIZE_190 # define MITK_PP_SEQ_SIZE_190(_) MITK_PP_SEQ_SIZE_191 # define MITK_PP_SEQ_SIZE_191(_) MITK_PP_SEQ_SIZE_192 # define MITK_PP_SEQ_SIZE_192(_) MITK_PP_SEQ_SIZE_193 # define MITK_PP_SEQ_SIZE_193(_) MITK_PP_SEQ_SIZE_194 # define MITK_PP_SEQ_SIZE_194(_) MITK_PP_SEQ_SIZE_195 # define MITK_PP_SEQ_SIZE_195(_) MITK_PP_SEQ_SIZE_196 # define MITK_PP_SEQ_SIZE_196(_) MITK_PP_SEQ_SIZE_197 # define MITK_PP_SEQ_SIZE_197(_) MITK_PP_SEQ_SIZE_198 # define MITK_PP_SEQ_SIZE_198(_) MITK_PP_SEQ_SIZE_199 # define MITK_PP_SEQ_SIZE_199(_) MITK_PP_SEQ_SIZE_200 # define MITK_PP_SEQ_SIZE_200(_) MITK_PP_SEQ_SIZE_201 # define MITK_PP_SEQ_SIZE_201(_) MITK_PP_SEQ_SIZE_202 # define MITK_PP_SEQ_SIZE_202(_) MITK_PP_SEQ_SIZE_203 # define MITK_PP_SEQ_SIZE_203(_) MITK_PP_SEQ_SIZE_204 # define MITK_PP_SEQ_SIZE_204(_) MITK_PP_SEQ_SIZE_205 # define MITK_PP_SEQ_SIZE_205(_) MITK_PP_SEQ_SIZE_206 # define MITK_PP_SEQ_SIZE_206(_) MITK_PP_SEQ_SIZE_207 # define MITK_PP_SEQ_SIZE_207(_) MITK_PP_SEQ_SIZE_208 # define MITK_PP_SEQ_SIZE_208(_) MITK_PP_SEQ_SIZE_209 # define MITK_PP_SEQ_SIZE_209(_) MITK_PP_SEQ_SIZE_210 # define MITK_PP_SEQ_SIZE_210(_) MITK_PP_SEQ_SIZE_211 # define MITK_PP_SEQ_SIZE_211(_) MITK_PP_SEQ_SIZE_212 # define MITK_PP_SEQ_SIZE_212(_) MITK_PP_SEQ_SIZE_213 # define MITK_PP_SEQ_SIZE_213(_) MITK_PP_SEQ_SIZE_214 # define MITK_PP_SEQ_SIZE_214(_) MITK_PP_SEQ_SIZE_215 # define MITK_PP_SEQ_SIZE_215(_) MITK_PP_SEQ_SIZE_216 # define MITK_PP_SEQ_SIZE_216(_) MITK_PP_SEQ_SIZE_217 # define MITK_PP_SEQ_SIZE_217(_) MITK_PP_SEQ_SIZE_218 # define MITK_PP_SEQ_SIZE_218(_) MITK_PP_SEQ_SIZE_219 # define MITK_PP_SEQ_SIZE_219(_) MITK_PP_SEQ_SIZE_220 # define MITK_PP_SEQ_SIZE_220(_) MITK_PP_SEQ_SIZE_221 # define MITK_PP_SEQ_SIZE_221(_) MITK_PP_SEQ_SIZE_222 # define MITK_PP_SEQ_SIZE_222(_) MITK_PP_SEQ_SIZE_223 # define MITK_PP_SEQ_SIZE_223(_) MITK_PP_SEQ_SIZE_224 # define MITK_PP_SEQ_SIZE_224(_) MITK_PP_SEQ_SIZE_225 # define MITK_PP_SEQ_SIZE_225(_) MITK_PP_SEQ_SIZE_226 # define MITK_PP_SEQ_SIZE_226(_) MITK_PP_SEQ_SIZE_227 # define MITK_PP_SEQ_SIZE_227(_) MITK_PP_SEQ_SIZE_228 # define MITK_PP_SEQ_SIZE_228(_) MITK_PP_SEQ_SIZE_229 # define MITK_PP_SEQ_SIZE_229(_) MITK_PP_SEQ_SIZE_230 # define MITK_PP_SEQ_SIZE_230(_) MITK_PP_SEQ_SIZE_231 # define MITK_PP_SEQ_SIZE_231(_) MITK_PP_SEQ_SIZE_232 # define MITK_PP_SEQ_SIZE_232(_) MITK_PP_SEQ_SIZE_233 # define MITK_PP_SEQ_SIZE_233(_) MITK_PP_SEQ_SIZE_234 # define MITK_PP_SEQ_SIZE_234(_) MITK_PP_SEQ_SIZE_235 # define MITK_PP_SEQ_SIZE_235(_) MITK_PP_SEQ_SIZE_236 # define MITK_PP_SEQ_SIZE_236(_) MITK_PP_SEQ_SIZE_237 # define MITK_PP_SEQ_SIZE_237(_) MITK_PP_SEQ_SIZE_238 # define MITK_PP_SEQ_SIZE_238(_) MITK_PP_SEQ_SIZE_239 # define MITK_PP_SEQ_SIZE_239(_) MITK_PP_SEQ_SIZE_240 # define MITK_PP_SEQ_SIZE_240(_) MITK_PP_SEQ_SIZE_241 # define MITK_PP_SEQ_SIZE_241(_) MITK_PP_SEQ_SIZE_242 # define MITK_PP_SEQ_SIZE_242(_) MITK_PP_SEQ_SIZE_243 # define MITK_PP_SEQ_SIZE_243(_) MITK_PP_SEQ_SIZE_244 # define MITK_PP_SEQ_SIZE_244(_) MITK_PP_SEQ_SIZE_245 # define MITK_PP_SEQ_SIZE_245(_) MITK_PP_SEQ_SIZE_246 # define MITK_PP_SEQ_SIZE_246(_) MITK_PP_SEQ_SIZE_247 # define MITK_PP_SEQ_SIZE_247(_) MITK_PP_SEQ_SIZE_248 # define MITK_PP_SEQ_SIZE_248(_) MITK_PP_SEQ_SIZE_249 # define MITK_PP_SEQ_SIZE_249(_) MITK_PP_SEQ_SIZE_250 # define MITK_PP_SEQ_SIZE_250(_) MITK_PP_SEQ_SIZE_251 # define MITK_PP_SEQ_SIZE_251(_) MITK_PP_SEQ_SIZE_252 # define MITK_PP_SEQ_SIZE_252(_) MITK_PP_SEQ_SIZE_253 # define MITK_PP_SEQ_SIZE_253(_) MITK_PP_SEQ_SIZE_254 # define MITK_PP_SEQ_SIZE_254(_) MITK_PP_SEQ_SIZE_255 # define MITK_PP_SEQ_SIZE_255(_) MITK_PP_SEQ_SIZE_256 # define MITK_PP_SEQ_SIZE_256(_) MITK_PP_SEQ_SIZE_257 # # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_0 0 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_1 1 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_2 2 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_3 3 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_4 4 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_5 5 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_6 6 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_7 7 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_8 8 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_9 9 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_10 10 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_11 11 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_12 12 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_13 13 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_14 14 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_15 15 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_16 16 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_17 17 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_18 18 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_19 19 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_20 20 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_21 21 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_22 22 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_23 23 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_24 24 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_25 25 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_26 26 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_27 27 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_28 28 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_29 29 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_30 30 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_31 31 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_32 32 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_33 33 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_34 34 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_35 35 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_36 36 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_37 37 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_38 38 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_39 39 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_40 40 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_41 41 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_42 42 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_43 43 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_44 44 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_45 45 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_46 46 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_47 47 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_48 48 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_49 49 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_50 50 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_51 51 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_52 52 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_53 53 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_54 54 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_55 55 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_56 56 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_57 57 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_58 58 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_59 59 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_60 60 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_61 61 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_62 62 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_63 63 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_64 64 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_65 65 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_66 66 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_67 67 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_68 68 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_69 69 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_70 70 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_71 71 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_72 72 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_73 73 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_74 74 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_75 75 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_76 76 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_77 77 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_78 78 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_79 79 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_80 80 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_81 81 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_82 82 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_83 83 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_84 84 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_85 85 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_86 86 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_87 87 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_88 88 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_89 89 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_90 90 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_91 91 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_92 92 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_93 93 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_94 94 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_95 95 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_96 96 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_97 97 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_98 98 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_99 99 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_100 100 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_101 101 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_102 102 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_103 103 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_104 104 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_105 105 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_106 106 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_107 107 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_108 108 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_109 109 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_110 110 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_111 111 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_112 112 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_113 113 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_114 114 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_115 115 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_116 116 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_117 117 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_118 118 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_119 119 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_120 120 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_121 121 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_122 122 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_123 123 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_124 124 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_125 125 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_126 126 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_127 127 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_128 128 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_129 129 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_130 130 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_131 131 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_132 132 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_133 133 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_134 134 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_135 135 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_136 136 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_137 137 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_138 138 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_139 139 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_140 140 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_141 141 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_142 142 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_143 143 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_144 144 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_145 145 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_146 146 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_147 147 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_148 148 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_149 149 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_150 150 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_151 151 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_152 152 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_153 153 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_154 154 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_155 155 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_156 156 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_157 157 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_158 158 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_159 159 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_160 160 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_161 161 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_162 162 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_163 163 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_164 164 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_165 165 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_166 166 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_167 167 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_168 168 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_169 169 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_170 170 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_171 171 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_172 172 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_173 173 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_174 174 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_175 175 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_176 176 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_177 177 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_178 178 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_179 179 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_180 180 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_181 181 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_182 182 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_183 183 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_184 184 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_185 185 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_186 186 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_187 187 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_188 188 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_189 189 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_190 190 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_191 191 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_192 192 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_193 193 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_194 194 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_195 195 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_196 196 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_197 197 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_198 198 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_199 199 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_200 200 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_201 201 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_202 202 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_203 203 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_204 204 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_205 205 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_206 206 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_207 207 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_208 208 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_209 209 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_210 210 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_211 211 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_212 212 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_213 213 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_214 214 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_215 215 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_216 216 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_217 217 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_218 218 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_219 219 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_220 220 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_221 221 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_222 222 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_223 223 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_224 224 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_225 225 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_226 226 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_227 227 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_228 228 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_229 229 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_230 230 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_231 231 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_232 232 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_233 233 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_234 234 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_235 235 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_236 236 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_237 237 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_238 238 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_239 239 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_240 240 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_241 241 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_242 242 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_243 243 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_244 244 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_245 245 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_246 246 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_247 247 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_248 248 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_249 249 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_250 250 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_251 251 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_252 252 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_253 253 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_254 254 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_255 255 # define MITK_PP_SEQ_SIZE_MITK_PP_SEQ_SIZE_256 256 # # endif diff --git a/Core/Code/Algorithms/mitkPPSeqToTuple.h b/Core/Code/Algorithms/mitkPPSeqToTuple.h index b1fdd59083..86ab353f3a 100644 --- a/Core/Code/Algorithms/mitkPPSeqToTuple.h +++ b/Core/Code/Algorithms/mitkPPSeqToTuple.h @@ -1,27 +1,42 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_SEQ_TO_TUPLE_HPP # define MITK_PREPROCESSOR_SEQ_TO_TUPLE_HPP # # include "mitkPPConfig.h" # include "mitkPPSeqEnum.h" # # /* MITK_PP_SEQ_TO_TUPLE */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_SEQ_TO_TUPLE(seq) (MITK_PP_SEQ_ENUM(seq)) # else # define MITK_PP_SEQ_TO_TUPLE(seq) MITK_PP_SEQ_TO_TUPLE_I(seq) # define MITK_PP_SEQ_TO_TUPLE_I(seq) (MITK_PP_SEQ_ENUM(seq)) # endif # # endif diff --git a/Core/Code/Algorithms/mitkPPStringize.h b/Core/Code/Algorithms/mitkPPStringize.h index 90c98c0341..11ea848d31 100644 --- a/Core/Code/Algorithms/mitkPPStringize.h +++ b/Core/Code/Algorithms/mitkPPStringize.h @@ -1,33 +1,48 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_STRINGIZE_HPP # define MITK_PREPROCESSOR_STRINGIZE_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_STRINGIZE */ # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_STRINGIZE(text) MITK_PP_STRINGIZE_A((text)) # define MITK_PP_STRINGIZE_A(arg) MITK_PP_STRINGIZE_I arg # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_STRINGIZE(text) MITK_PP_STRINGIZE_OO((text)) # define MITK_PP_STRINGIZE_OO(par) MITK_PP_STRINGIZE_I ## par # else # define MITK_PP_STRINGIZE(text) MITK_PP_STRINGIZE_I(text) # endif # # define MITK_PP_STRINGIZE_I(text) #text # # endif diff --git a/Core/Code/Algorithms/mitkPPTupleEat.h b/Core/Code/Algorithms/mitkPPTupleEat.h index b33f4fb520..0b4ccc3721 100644 --- a/Core/Code/Algorithms/mitkPPTupleEat.h +++ b/Core/Code/Algorithms/mitkPPTupleEat.h @@ -1,57 +1,72 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_TUPLE_EAT_HPP # define MITK_PREPROCESSOR_TUPLE_EAT_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_TUPLE_EAT */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_TUPLE_EAT(size) MITK_PP_TUPLE_EAT_I(size) # else # define MITK_PP_TUPLE_EAT(size) MITK_PP_TUPLE_EAT_OO((size)) # define MITK_PP_TUPLE_EAT_OO(par) MITK_PP_TUPLE_EAT_I ## par # endif # # define MITK_PP_TUPLE_EAT_I(size) MITK_PP_TUPLE_EAT_ ## size # # define MITK_PP_TUPLE_EAT_0() # define MITK_PP_TUPLE_EAT_1(a) # define MITK_PP_TUPLE_EAT_2(a, b) # define MITK_PP_TUPLE_EAT_3(a, b, c) # define MITK_PP_TUPLE_EAT_4(a, b, c, d) # define MITK_PP_TUPLE_EAT_5(a, b, c, d, e) # define MITK_PP_TUPLE_EAT_6(a, b, c, d, e, f) # define MITK_PP_TUPLE_EAT_7(a, b, c, d, e, f, g) # define MITK_PP_TUPLE_EAT_8(a, b, c, d, e, f, g, h) # define MITK_PP_TUPLE_EAT_9(a, b, c, d, e, f, g, h, i) # define MITK_PP_TUPLE_EAT_10(a, b, c, d, e, f, g, h, i, j) # define MITK_PP_TUPLE_EAT_11(a, b, c, d, e, f, g, h, i, j, k) # define MITK_PP_TUPLE_EAT_12(a, b, c, d, e, f, g, h, i, j, k, l) # define MITK_PP_TUPLE_EAT_13(a, b, c, d, e, f, g, h, i, j, k, l, m) # define MITK_PP_TUPLE_EAT_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) # define MITK_PP_TUPLE_EAT_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) # define MITK_PP_TUPLE_EAT_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) # define MITK_PP_TUPLE_EAT_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) # define MITK_PP_TUPLE_EAT_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) # define MITK_PP_TUPLE_EAT_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) # define MITK_PP_TUPLE_EAT_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) # define MITK_PP_TUPLE_EAT_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) # define MITK_PP_TUPLE_EAT_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) # define MITK_PP_TUPLE_EAT_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) # define MITK_PP_TUPLE_EAT_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) # define MITK_PP_TUPLE_EAT_25(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) # # endif diff --git a/Core/Code/Algorithms/mitkPPTupleElem.h b/Core/Code/Algorithms/mitkPPTupleElem.h index 5fcc60aee7..844fcd4865 100644 --- a/Core/Code/Algorithms/mitkPPTupleElem.h +++ b/Core/Code/Algorithms/mitkPPTupleElem.h @@ -1,385 +1,400 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* Copyright (C) 2001 # * Housemarque Oy # * http://www.housemarque.com # * # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # */ # # /* Revised by Paul Mensonides (2002) */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_TUPLE_ELEM_HPP # define MITK_PREPROCESSOR_TUPLE_ELEM_HPP # # include "mitkPPConfig.h" # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_TUPLE_ELEM(size, index, tuple) MITK_PP_TUPLE_ELEM_I(size, index, tuple) # else # define MITK_PP_TUPLE_ELEM(size, index, tuple) MITK_PP_TUPLE_ELEM_OO((size, index, tuple)) # define MITK_PP_TUPLE_ELEM_OO(par) MITK_PP_TUPLE_ELEM_I ## par # endif # # if MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_TUPLE_ELEM_I(s, i, t) MITK_PP_TUPLE_ELEM_ ## s ## _ ## i ## t # elif MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MSVC() # define MITK_PP_TUPLE_ELEM_I(s, i, t) MITK_PP_TUPLE_ELEM_II(MITK_PP_TUPLE_ELEM_ ## s ## _ ## i t) # define MITK_PP_TUPLE_ELEM_II(res) res # else # define MITK_PP_TUPLE_ELEM_I(s, i, t) MITK_PP_TUPLE_ELEM_ ## s ## _ ## i t # endif # # define MITK_PP_TUPLE_ELEM_1_0(a) a # # define MITK_PP_TUPLE_ELEM_2_0(a, b) a # define MITK_PP_TUPLE_ELEM_2_1(a, b) b # # define MITK_PP_TUPLE_ELEM_3_0(a, b, c) a # define MITK_PP_TUPLE_ELEM_3_1(a, b, c) b # define MITK_PP_TUPLE_ELEM_3_2(a, b, c) c # # define MITK_PP_TUPLE_ELEM_4_0(a, b, c, d) a # define MITK_PP_TUPLE_ELEM_4_1(a, b, c, d) b # define MITK_PP_TUPLE_ELEM_4_2(a, b, c, d) c # define MITK_PP_TUPLE_ELEM_4_3(a, b, c, d) d # # define MITK_PP_TUPLE_ELEM_5_0(a, b, c, d, e) a # define MITK_PP_TUPLE_ELEM_5_1(a, b, c, d, e) b # define MITK_PP_TUPLE_ELEM_5_2(a, b, c, d, e) c # define MITK_PP_TUPLE_ELEM_5_3(a, b, c, d, e) d # define MITK_PP_TUPLE_ELEM_5_4(a, b, c, d, e) e # # define MITK_PP_TUPLE_ELEM_6_0(a, b, c, d, e, f) a # define MITK_PP_TUPLE_ELEM_6_1(a, b, c, d, e, f) b # define MITK_PP_TUPLE_ELEM_6_2(a, b, c, d, e, f) c # define MITK_PP_TUPLE_ELEM_6_3(a, b, c, d, e, f) d # define MITK_PP_TUPLE_ELEM_6_4(a, b, c, d, e, f) e # define MITK_PP_TUPLE_ELEM_6_5(a, b, c, d, e, f) f # # define MITK_PP_TUPLE_ELEM_7_0(a, b, c, d, e, f, g) a # define MITK_PP_TUPLE_ELEM_7_1(a, b, c, d, e, f, g) b # define MITK_PP_TUPLE_ELEM_7_2(a, b, c, d, e, f, g) c # define MITK_PP_TUPLE_ELEM_7_3(a, b, c, d, e, f, g) d # define MITK_PP_TUPLE_ELEM_7_4(a, b, c, d, e, f, g) e # define MITK_PP_TUPLE_ELEM_7_5(a, b, c, d, e, f, g) f # define MITK_PP_TUPLE_ELEM_7_6(a, b, c, d, e, f, g) g # # define MITK_PP_TUPLE_ELEM_8_0(a, b, c, d, e, f, g, h) a # define MITK_PP_TUPLE_ELEM_8_1(a, b, c, d, e, f, g, h) b # define MITK_PP_TUPLE_ELEM_8_2(a, b, c, d, e, f, g, h) c # define MITK_PP_TUPLE_ELEM_8_3(a, b, c, d, e, f, g, h) d # define MITK_PP_TUPLE_ELEM_8_4(a, b, c, d, e, f, g, h) e # define MITK_PP_TUPLE_ELEM_8_5(a, b, c, d, e, f, g, h) f # define MITK_PP_TUPLE_ELEM_8_6(a, b, c, d, e, f, g, h) g # define MITK_PP_TUPLE_ELEM_8_7(a, b, c, d, e, f, g, h) h # # define MITK_PP_TUPLE_ELEM_9_0(a, b, c, d, e, f, g, h, i) a # define MITK_PP_TUPLE_ELEM_9_1(a, b, c, d, e, f, g, h, i) b # define MITK_PP_TUPLE_ELEM_9_2(a, b, c, d, e, f, g, h, i) c # define MITK_PP_TUPLE_ELEM_9_3(a, b, c, d, e, f, g, h, i) d # define MITK_PP_TUPLE_ELEM_9_4(a, b, c, d, e, f, g, h, i) e # define MITK_PP_TUPLE_ELEM_9_5(a, b, c, d, e, f, g, h, i) f # define MITK_PP_TUPLE_ELEM_9_6(a, b, c, d, e, f, g, h, i) g # define MITK_PP_TUPLE_ELEM_9_7(a, b, c, d, e, f, g, h, i) h # define MITK_PP_TUPLE_ELEM_9_8(a, b, c, d, e, f, g, h, i) i # # define MITK_PP_TUPLE_ELEM_10_0(a, b, c, d, e, f, g, h, i, j) a # define MITK_PP_TUPLE_ELEM_10_1(a, b, c, d, e, f, g, h, i, j) b # define MITK_PP_TUPLE_ELEM_10_2(a, b, c, d, e, f, g, h, i, j) c # define MITK_PP_TUPLE_ELEM_10_3(a, b, c, d, e, f, g, h, i, j) d # define MITK_PP_TUPLE_ELEM_10_4(a, b, c, d, e, f, g, h, i, j) e # define MITK_PP_TUPLE_ELEM_10_5(a, b, c, d, e, f, g, h, i, j) f # define MITK_PP_TUPLE_ELEM_10_6(a, b, c, d, e, f, g, h, i, j) g # define MITK_PP_TUPLE_ELEM_10_7(a, b, c, d, e, f, g, h, i, j) h # define MITK_PP_TUPLE_ELEM_10_8(a, b, c, d, e, f, g, h, i, j) i # define MITK_PP_TUPLE_ELEM_10_9(a, b, c, d, e, f, g, h, i, j) j # # define MITK_PP_TUPLE_ELEM_11_0(a, b, c, d, e, f, g, h, i, j, k) a # define MITK_PP_TUPLE_ELEM_11_1(a, b, c, d, e, f, g, h, i, j, k) b # define MITK_PP_TUPLE_ELEM_11_2(a, b, c, d, e, f, g, h, i, j, k) c # define MITK_PP_TUPLE_ELEM_11_3(a, b, c, d, e, f, g, h, i, j, k) d # define MITK_PP_TUPLE_ELEM_11_4(a, b, c, d, e, f, g, h, i, j, k) e # define MITK_PP_TUPLE_ELEM_11_5(a, b, c, d, e, f, g, h, i, j, k) f # define MITK_PP_TUPLE_ELEM_11_6(a, b, c, d, e, f, g, h, i, j, k) g # define MITK_PP_TUPLE_ELEM_11_7(a, b, c, d, e, f, g, h, i, j, k) h # define MITK_PP_TUPLE_ELEM_11_8(a, b, c, d, e, f, g, h, i, j, k) i # define MITK_PP_TUPLE_ELEM_11_9(a, b, c, d, e, f, g, h, i, j, k) j # define MITK_PP_TUPLE_ELEM_11_10(a, b, c, d, e, f, g, h, i, j, k) k # # define MITK_PP_TUPLE_ELEM_12_0(a, b, c, d, e, f, g, h, i, j, k, l) a # define MITK_PP_TUPLE_ELEM_12_1(a, b, c, d, e, f, g, h, i, j, k, l) b # define MITK_PP_TUPLE_ELEM_12_2(a, b, c, d, e, f, g, h, i, j, k, l) c # define MITK_PP_TUPLE_ELEM_12_3(a, b, c, d, e, f, g, h, i, j, k, l) d # define MITK_PP_TUPLE_ELEM_12_4(a, b, c, d, e, f, g, h, i, j, k, l) e # define MITK_PP_TUPLE_ELEM_12_5(a, b, c, d, e, f, g, h, i, j, k, l) f # define MITK_PP_TUPLE_ELEM_12_6(a, b, c, d, e, f, g, h, i, j, k, l) g # define MITK_PP_TUPLE_ELEM_12_7(a, b, c, d, e, f, g, h, i, j, k, l) h # define MITK_PP_TUPLE_ELEM_12_8(a, b, c, d, e, f, g, h, i, j, k, l) i # define MITK_PP_TUPLE_ELEM_12_9(a, b, c, d, e, f, g, h, i, j, k, l) j # define MITK_PP_TUPLE_ELEM_12_10(a, b, c, d, e, f, g, h, i, j, k, l) k # define MITK_PP_TUPLE_ELEM_12_11(a, b, c, d, e, f, g, h, i, j, k, l) l # # define MITK_PP_TUPLE_ELEM_13_0(a, b, c, d, e, f, g, h, i, j, k, l, m) a # define MITK_PP_TUPLE_ELEM_13_1(a, b, c, d, e, f, g, h, i, j, k, l, m) b # define MITK_PP_TUPLE_ELEM_13_2(a, b, c, d, e, f, g, h, i, j, k, l, m) c # define MITK_PP_TUPLE_ELEM_13_3(a, b, c, d, e, f, g, h, i, j, k, l, m) d # define MITK_PP_TUPLE_ELEM_13_4(a, b, c, d, e, f, g, h, i, j, k, l, m) e # define MITK_PP_TUPLE_ELEM_13_5(a, b, c, d, e, f, g, h, i, j, k, l, m) f # define MITK_PP_TUPLE_ELEM_13_6(a, b, c, d, e, f, g, h, i, j, k, l, m) g # define MITK_PP_TUPLE_ELEM_13_7(a, b, c, d, e, f, g, h, i, j, k, l, m) h # define MITK_PP_TUPLE_ELEM_13_8(a, b, c, d, e, f, g, h, i, j, k, l, m) i # define MITK_PP_TUPLE_ELEM_13_9(a, b, c, d, e, f, g, h, i, j, k, l, m) j # define MITK_PP_TUPLE_ELEM_13_10(a, b, c, d, e, f, g, h, i, j, k, l, m) k # define MITK_PP_TUPLE_ELEM_13_11(a, b, c, d, e, f, g, h, i, j, k, l, m) l # define MITK_PP_TUPLE_ELEM_13_12(a, b, c, d, e, f, g, h, i, j, k, l, m) m # # define MITK_PP_TUPLE_ELEM_14_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n) a # define MITK_PP_TUPLE_ELEM_14_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n) b # define MITK_PP_TUPLE_ELEM_14_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n) c # define MITK_PP_TUPLE_ELEM_14_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n) d # define MITK_PP_TUPLE_ELEM_14_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n) e # define MITK_PP_TUPLE_ELEM_14_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n) f # define MITK_PP_TUPLE_ELEM_14_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n) g # define MITK_PP_TUPLE_ELEM_14_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n) h # define MITK_PP_TUPLE_ELEM_14_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n) i # define MITK_PP_TUPLE_ELEM_14_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n) j # define MITK_PP_TUPLE_ELEM_14_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n) k # define MITK_PP_TUPLE_ELEM_14_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n) l # define MITK_PP_TUPLE_ELEM_14_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n) m # define MITK_PP_TUPLE_ELEM_14_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n) n # # define MITK_PP_TUPLE_ELEM_15_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) a # define MITK_PP_TUPLE_ELEM_15_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) b # define MITK_PP_TUPLE_ELEM_15_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) c # define MITK_PP_TUPLE_ELEM_15_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) d # define MITK_PP_TUPLE_ELEM_15_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) e # define MITK_PP_TUPLE_ELEM_15_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) f # define MITK_PP_TUPLE_ELEM_15_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) g # define MITK_PP_TUPLE_ELEM_15_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) h # define MITK_PP_TUPLE_ELEM_15_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) i # define MITK_PP_TUPLE_ELEM_15_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) j # define MITK_PP_TUPLE_ELEM_15_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) k # define MITK_PP_TUPLE_ELEM_15_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) l # define MITK_PP_TUPLE_ELEM_15_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) m # define MITK_PP_TUPLE_ELEM_15_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) n # define MITK_PP_TUPLE_ELEM_15_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) o # # define MITK_PP_TUPLE_ELEM_16_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) a # define MITK_PP_TUPLE_ELEM_16_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) b # define MITK_PP_TUPLE_ELEM_16_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) c # define MITK_PP_TUPLE_ELEM_16_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) d # define MITK_PP_TUPLE_ELEM_16_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) e # define MITK_PP_TUPLE_ELEM_16_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) f # define MITK_PP_TUPLE_ELEM_16_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) g # define MITK_PP_TUPLE_ELEM_16_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) h # define MITK_PP_TUPLE_ELEM_16_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) i # define MITK_PP_TUPLE_ELEM_16_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) j # define MITK_PP_TUPLE_ELEM_16_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) k # define MITK_PP_TUPLE_ELEM_16_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) l # define MITK_PP_TUPLE_ELEM_16_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) m # define MITK_PP_TUPLE_ELEM_16_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) n # define MITK_PP_TUPLE_ELEM_16_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) o # define MITK_PP_TUPLE_ELEM_16_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) p # # define MITK_PP_TUPLE_ELEM_17_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) a # define MITK_PP_TUPLE_ELEM_17_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) b # define MITK_PP_TUPLE_ELEM_17_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) c # define MITK_PP_TUPLE_ELEM_17_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) d # define MITK_PP_TUPLE_ELEM_17_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) e # define MITK_PP_TUPLE_ELEM_17_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) f # define MITK_PP_TUPLE_ELEM_17_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) g # define MITK_PP_TUPLE_ELEM_17_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) h # define MITK_PP_TUPLE_ELEM_17_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) i # define MITK_PP_TUPLE_ELEM_17_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) j # define MITK_PP_TUPLE_ELEM_17_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) k # define MITK_PP_TUPLE_ELEM_17_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) l # define MITK_PP_TUPLE_ELEM_17_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) m # define MITK_PP_TUPLE_ELEM_17_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) n # define MITK_PP_TUPLE_ELEM_17_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) o # define MITK_PP_TUPLE_ELEM_17_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) p # define MITK_PP_TUPLE_ELEM_17_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) q # # define MITK_PP_TUPLE_ELEM_18_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) a # define MITK_PP_TUPLE_ELEM_18_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) b # define MITK_PP_TUPLE_ELEM_18_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) c # define MITK_PP_TUPLE_ELEM_18_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) d # define MITK_PP_TUPLE_ELEM_18_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) e # define MITK_PP_TUPLE_ELEM_18_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) f # define MITK_PP_TUPLE_ELEM_18_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) g # define MITK_PP_TUPLE_ELEM_18_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) h # define MITK_PP_TUPLE_ELEM_18_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) i # define MITK_PP_TUPLE_ELEM_18_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) j # define MITK_PP_TUPLE_ELEM_18_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) k # define MITK_PP_TUPLE_ELEM_18_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) l # define MITK_PP_TUPLE_ELEM_18_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) m # define MITK_PP_TUPLE_ELEM_18_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) n # define MITK_PP_TUPLE_ELEM_18_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) o # define MITK_PP_TUPLE_ELEM_18_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) p # define MITK_PP_TUPLE_ELEM_18_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) q # define MITK_PP_TUPLE_ELEM_18_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) r # # define MITK_PP_TUPLE_ELEM_19_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) a # define MITK_PP_TUPLE_ELEM_19_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) b # define MITK_PP_TUPLE_ELEM_19_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) c # define MITK_PP_TUPLE_ELEM_19_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) d # define MITK_PP_TUPLE_ELEM_19_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) e # define MITK_PP_TUPLE_ELEM_19_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) f # define MITK_PP_TUPLE_ELEM_19_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) g # define MITK_PP_TUPLE_ELEM_19_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) h # define MITK_PP_TUPLE_ELEM_19_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) i # define MITK_PP_TUPLE_ELEM_19_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) j # define MITK_PP_TUPLE_ELEM_19_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) k # define MITK_PP_TUPLE_ELEM_19_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) l # define MITK_PP_TUPLE_ELEM_19_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) m # define MITK_PP_TUPLE_ELEM_19_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) n # define MITK_PP_TUPLE_ELEM_19_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) o # define MITK_PP_TUPLE_ELEM_19_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) p # define MITK_PP_TUPLE_ELEM_19_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) q # define MITK_PP_TUPLE_ELEM_19_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) r # define MITK_PP_TUPLE_ELEM_19_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) s # # define MITK_PP_TUPLE_ELEM_20_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) a # define MITK_PP_TUPLE_ELEM_20_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) b # define MITK_PP_TUPLE_ELEM_20_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) c # define MITK_PP_TUPLE_ELEM_20_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) d # define MITK_PP_TUPLE_ELEM_20_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) e # define MITK_PP_TUPLE_ELEM_20_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) f # define MITK_PP_TUPLE_ELEM_20_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) g # define MITK_PP_TUPLE_ELEM_20_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) h # define MITK_PP_TUPLE_ELEM_20_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) i # define MITK_PP_TUPLE_ELEM_20_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) j # define MITK_PP_TUPLE_ELEM_20_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) k # define MITK_PP_TUPLE_ELEM_20_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) l # define MITK_PP_TUPLE_ELEM_20_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) m # define MITK_PP_TUPLE_ELEM_20_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) n # define MITK_PP_TUPLE_ELEM_20_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) o # define MITK_PP_TUPLE_ELEM_20_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) p # define MITK_PP_TUPLE_ELEM_20_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) q # define MITK_PP_TUPLE_ELEM_20_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) r # define MITK_PP_TUPLE_ELEM_20_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) s # define MITK_PP_TUPLE_ELEM_20_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) t # # define MITK_PP_TUPLE_ELEM_21_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) a # define MITK_PP_TUPLE_ELEM_21_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) b # define MITK_PP_TUPLE_ELEM_21_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) c # define MITK_PP_TUPLE_ELEM_21_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) d # define MITK_PP_TUPLE_ELEM_21_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) e # define MITK_PP_TUPLE_ELEM_21_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) f # define MITK_PP_TUPLE_ELEM_21_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) g # define MITK_PP_TUPLE_ELEM_21_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) h # define MITK_PP_TUPLE_ELEM_21_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) i # define MITK_PP_TUPLE_ELEM_21_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) j # define MITK_PP_TUPLE_ELEM_21_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) k # define MITK_PP_TUPLE_ELEM_21_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) l # define MITK_PP_TUPLE_ELEM_21_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) m # define MITK_PP_TUPLE_ELEM_21_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) n # define MITK_PP_TUPLE_ELEM_21_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) o # define MITK_PP_TUPLE_ELEM_21_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) p # define MITK_PP_TUPLE_ELEM_21_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) q # define MITK_PP_TUPLE_ELEM_21_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) r # define MITK_PP_TUPLE_ELEM_21_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) s # define MITK_PP_TUPLE_ELEM_21_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) t # define MITK_PP_TUPLE_ELEM_21_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) u # # define MITK_PP_TUPLE_ELEM_22_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) a # define MITK_PP_TUPLE_ELEM_22_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) b # define MITK_PP_TUPLE_ELEM_22_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) c # define MITK_PP_TUPLE_ELEM_22_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) d # define MITK_PP_TUPLE_ELEM_22_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) e # define MITK_PP_TUPLE_ELEM_22_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) f # define MITK_PP_TUPLE_ELEM_22_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) g # define MITK_PP_TUPLE_ELEM_22_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) h # define MITK_PP_TUPLE_ELEM_22_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) i # define MITK_PP_TUPLE_ELEM_22_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) j # define MITK_PP_TUPLE_ELEM_22_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) k # define MITK_PP_TUPLE_ELEM_22_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) l # define MITK_PP_TUPLE_ELEM_22_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) m # define MITK_PP_TUPLE_ELEM_22_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) n # define MITK_PP_TUPLE_ELEM_22_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) o # define MITK_PP_TUPLE_ELEM_22_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) p # define MITK_PP_TUPLE_ELEM_22_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) q # define MITK_PP_TUPLE_ELEM_22_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) r # define MITK_PP_TUPLE_ELEM_22_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) s # define MITK_PP_TUPLE_ELEM_22_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) t # define MITK_PP_TUPLE_ELEM_22_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) u # define MITK_PP_TUPLE_ELEM_22_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) v # # define MITK_PP_TUPLE_ELEM_23_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) a # define MITK_PP_TUPLE_ELEM_23_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) b # define MITK_PP_TUPLE_ELEM_23_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) c # define MITK_PP_TUPLE_ELEM_23_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) d # define MITK_PP_TUPLE_ELEM_23_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) e # define MITK_PP_TUPLE_ELEM_23_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) f # define MITK_PP_TUPLE_ELEM_23_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) g # define MITK_PP_TUPLE_ELEM_23_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) h # define MITK_PP_TUPLE_ELEM_23_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) i # define MITK_PP_TUPLE_ELEM_23_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) j # define MITK_PP_TUPLE_ELEM_23_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) k # define MITK_PP_TUPLE_ELEM_23_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) l # define MITK_PP_TUPLE_ELEM_23_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) m # define MITK_PP_TUPLE_ELEM_23_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) n # define MITK_PP_TUPLE_ELEM_23_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) o # define MITK_PP_TUPLE_ELEM_23_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) p # define MITK_PP_TUPLE_ELEM_23_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) q # define MITK_PP_TUPLE_ELEM_23_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) r # define MITK_PP_TUPLE_ELEM_23_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) s # define MITK_PP_TUPLE_ELEM_23_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) t # define MITK_PP_TUPLE_ELEM_23_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) u # define MITK_PP_TUPLE_ELEM_23_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) v # define MITK_PP_TUPLE_ELEM_23_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) w # # define MITK_PP_TUPLE_ELEM_24_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) a # define MITK_PP_TUPLE_ELEM_24_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) b # define MITK_PP_TUPLE_ELEM_24_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) c # define MITK_PP_TUPLE_ELEM_24_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) d # define MITK_PP_TUPLE_ELEM_24_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) e # define MITK_PP_TUPLE_ELEM_24_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) f # define MITK_PP_TUPLE_ELEM_24_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) g # define MITK_PP_TUPLE_ELEM_24_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) h # define MITK_PP_TUPLE_ELEM_24_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) i # define MITK_PP_TUPLE_ELEM_24_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) j # define MITK_PP_TUPLE_ELEM_24_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) k # define MITK_PP_TUPLE_ELEM_24_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) l # define MITK_PP_TUPLE_ELEM_24_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) m # define MITK_PP_TUPLE_ELEM_24_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) n # define MITK_PP_TUPLE_ELEM_24_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) o # define MITK_PP_TUPLE_ELEM_24_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) p # define MITK_PP_TUPLE_ELEM_24_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) q # define MITK_PP_TUPLE_ELEM_24_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) r # define MITK_PP_TUPLE_ELEM_24_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) s # define MITK_PP_TUPLE_ELEM_24_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) t # define MITK_PP_TUPLE_ELEM_24_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) u # define MITK_PP_TUPLE_ELEM_24_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) v # define MITK_PP_TUPLE_ELEM_24_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) w # define MITK_PP_TUPLE_ELEM_24_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) x # # define MITK_PP_TUPLE_ELEM_25_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) a # define MITK_PP_TUPLE_ELEM_25_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) b # define MITK_PP_TUPLE_ELEM_25_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) c # define MITK_PP_TUPLE_ELEM_25_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) d # define MITK_PP_TUPLE_ELEM_25_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) e # define MITK_PP_TUPLE_ELEM_25_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) f # define MITK_PP_TUPLE_ELEM_25_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) g # define MITK_PP_TUPLE_ELEM_25_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) h # define MITK_PP_TUPLE_ELEM_25_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) i # define MITK_PP_TUPLE_ELEM_25_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) j # define MITK_PP_TUPLE_ELEM_25_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) k # define MITK_PP_TUPLE_ELEM_25_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) l # define MITK_PP_TUPLE_ELEM_25_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) m # define MITK_PP_TUPLE_ELEM_25_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) n # define MITK_PP_TUPLE_ELEM_25_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) o # define MITK_PP_TUPLE_ELEM_25_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) p # define MITK_PP_TUPLE_ELEM_25_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) q # define MITK_PP_TUPLE_ELEM_25_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) r # define MITK_PP_TUPLE_ELEM_25_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) s # define MITK_PP_TUPLE_ELEM_25_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) t # define MITK_PP_TUPLE_ELEM_25_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) u # define MITK_PP_TUPLE_ELEM_25_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) v # define MITK_PP_TUPLE_ELEM_25_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) w # define MITK_PP_TUPLE_ELEM_25_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) x # define MITK_PP_TUPLE_ELEM_25_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) y # # endif diff --git a/Core/Code/Algorithms/mitkPPTupleRem.h b/Core/Code/Algorithms/mitkPPTupleRem.h index f9ededef69..e0909c180f 100644 --- a/Core/Code/Algorithms/mitkPPTupleRem.h +++ b/Core/Code/Algorithms/mitkPPTupleRem.h @@ -1,72 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ # /* ************************************************************************** # * * # * (C) Copyright Paul Mensonides 2002. # * Distributed under the Boost Software License, Version 1.0. (See # * accompanying file LICENSE_1_0.txt or copy at # * http://www.boost.org/LICENSE_1_0.txt) # * * # ************************************************************************** */ # # /* See http://www.boost.org for most recent version. */ # # ifndef MITK_PREPROCESSOR_TUPLE_REM_HPP # define MITK_PREPROCESSOR_TUPLE_REM_HPP # # include "mitkPPConfig.h" # # /* MITK_PP_TUPLE_REM */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_TUPLE_REM(size) MITK_PP_TUPLE_REM_I(size) # else # define MITK_PP_TUPLE_REM(size) MITK_PP_TUPLE_REM_OO((size)) # define MITK_PP_TUPLE_REM_OO(par) MITK_PP_TUPLE_REM_I ## par # endif # # define MITK_PP_TUPLE_REM_I(size) MITK_PP_TUPLE_REM_ ## size # # define MITK_PP_TUPLE_REM_0() # define MITK_PP_TUPLE_REM_1(a) a # define MITK_PP_TUPLE_REM_2(a, b) a, b # define MITK_PP_TUPLE_REM_3(a, b, c) a, b, c # define MITK_PP_TUPLE_REM_4(a, b, c, d) a, b, c, d # define MITK_PP_TUPLE_REM_5(a, b, c, d, e) a, b, c, d, e # define MITK_PP_TUPLE_REM_6(a, b, c, d, e, f) a, b, c, d, e, f # define MITK_PP_TUPLE_REM_7(a, b, c, d, e, f, g) a, b, c, d, e, f, g # define MITK_PP_TUPLE_REM_8(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h # define MITK_PP_TUPLE_REM_9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i # define MITK_PP_TUPLE_REM_10(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j # define MITK_PP_TUPLE_REM_11(a, b, c, d, e, f, g, h, i, j, k) a, b, c, d, e, f, g, h, i, j, k # define MITK_PP_TUPLE_REM_12(a, b, c, d, e, f, g, h, i, j, k, l) a, b, c, d, e, f, g, h, i, j, k, l # define MITK_PP_TUPLE_REM_13(a, b, c, d, e, f, g, h, i, j, k, l, m) a, b, c, d, e, f, g, h, i, j, k, l, m # define MITK_PP_TUPLE_REM_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) a, b, c, d, e, f, g, h, i, j, k, l, m, n # define MITK_PP_TUPLE_REM_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o # define MITK_PP_TUPLE_REM_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p # define MITK_PP_TUPLE_REM_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q # define MITK_PP_TUPLE_REM_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r # define MITK_PP_TUPLE_REM_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s # define MITK_PP_TUPLE_REM_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t # define MITK_PP_TUPLE_REM_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u # define MITK_PP_TUPLE_REM_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v # define MITK_PP_TUPLE_REM_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w # define MITK_PP_TUPLE_REM_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x # define MITK_PP_TUPLE_REM_25(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y # # /* MITK_PP_TUPLE_REM_CTOR */ # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_EDG() # define MITK_PP_TUPLE_REM_CTOR(size, tuple) MITK_PP_TUPLE_REM_CTOR_I(MITK_PP_TUPLE_REM(size), tuple) # else # define MITK_PP_TUPLE_REM_CTOR(size, tuple) MITK_PP_TUPLE_REM_CTOR_D(size, tuple) # define MITK_PP_TUPLE_REM_CTOR_D(size, tuple) MITK_PP_TUPLE_REM_CTOR_I(MITK_PP_TUPLE_REM(size), tuple) # endif # # if ~MITK_PP_CONFIG_FLAGS() & MITK_PP_CONFIG_MWCC() # define MITK_PP_TUPLE_REM_CTOR_I(ext, tuple) ext tuple # else # define MITK_PP_TUPLE_REM_CTOR_I(ext, tuple) MITK_PP_TUPLE_REM_CTOR_OO((ext, tuple)) # define MITK_PP_TUPLE_REM_CTOR_OO(par) MITK_PP_TUPLE_REM_CTOR_II ## par # define MITK_PP_TUPLE_REM_CTOR_II(ext, tuple) ext ## tuple # endif # # endif diff --git a/Core/Code/Controllers/mitkPlanePositionManager.cpp b/Core/Code/Controllers/mitkPlanePositionManager.cpp index 5e2bde6bff..67c3e76b3a 100644 --- a/Core/Code/Controllers/mitkPlanePositionManager.cpp +++ b/Core/Code/Controllers/mitkPlanePositionManager.cpp @@ -1,94 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPlanePositionManager.h" #include "mitkInteractionConst.h" #include #include #include mitk::PlanePositionManagerService::PlanePositionManagerService() { } mitk::PlanePositionManagerService::~PlanePositionManagerService() { for (unsigned int i = 0; i < m_PositionList.size(); i++) { delete m_PositionList.at(i); } } unsigned int mitk::PlanePositionManagerService::AddNewPlanePosition ( const Geometry2D* plane, unsigned int sliceIndex ) { for (unsigned int i = 0; i < m_PositionList.size(); i++) { if (m_PositionList.at(i) != 0) { bool isSameMatrix(true); bool isSameOffset(true); isSameOffset = mitk::Equal(m_PositionList.at(i)->GetTransform()->GetOffset(), plane->GetIndexToWorldTransform()->GetOffset()); if(!isSameOffset || sliceIndex != m_PositionList.at(i)->GetPos()) continue; isSameMatrix = mitk::MatrixEqualElementWise(m_PositionList.at(i)->GetTransform()->GetMatrix(), plane->GetIndexToWorldTransform()->GetMatrix()); if(isSameMatrix) return i; } } AffineTransform3D::Pointer transform = AffineTransform3D::New(); Matrix3D matrix; matrix.GetVnlMatrix().set_column(0, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0)); matrix.GetVnlMatrix().set_column(1, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1)); matrix.GetVnlMatrix().set_column(2, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)); transform->SetMatrix(matrix); transform->SetOffset(plane->GetIndexToWorldTransform()->GetOffset()); mitk::Vector3D direction; direction[0] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[0]; direction[1] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[1]; direction[2] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[2]; direction.Normalize(); mitk::RestorePlanePositionOperation* newOp = new mitk::RestorePlanePositionOperation (OpRESTOREPLANEPOSITION, plane->GetExtent(0), plane->GetExtent(1), plane->GetSpacing(), sliceIndex, direction, transform); m_PositionList.push_back( newOp ); return GetNumberOfPlanePositions()-1; } bool mitk::PlanePositionManagerService::RemovePlanePosition( unsigned int ID ) { if (m_PositionList.size() > ID) { m_PositionList.erase(m_PositionList.begin()+ID); return true; } else { return false; } } mitk::RestorePlanePositionOperation* mitk::PlanePositionManagerService::GetPlanePosition ( unsigned int ID ) { if ( ID < m_PositionList.size() ) { return m_PositionList.at(ID); } else { MITK_WARN<<"GetPlanePosition returned NULL!"; return 0; } } unsigned int mitk::PlanePositionManagerService::GetNumberOfPlanePositions() { return m_PositionList.size(); } void mitk::PlanePositionManagerService::RemoveAllPlanePositions() { m_PositionList.clear(); } diff --git a/Core/Code/DataManagement/mitkChannelDescriptor.cpp b/Core/Code/DataManagement/mitkChannelDescriptor.cpp index 93f6299e32..cb112302bc 100644 --- a/Core/Code/DataManagement/mitkChannelDescriptor.cpp +++ b/Core/Code/DataManagement/mitkChannelDescriptor.cpp @@ -1,38 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkChannelDescriptor.h" #include "mitkMemoryUtilities.h" mitk::ChannelDescriptor::ChannelDescriptor( mitk::PixelType type, size_t numOfElements, bool /*allocate*/) : m_PixelType(NULL), m_Size(numOfElements), m_Data(NULL) { m_PixelType = new PixelType(type); //MITK_INFO << "Entering ChannelDescriptor constructor."; } /* void mitk::ChannelDescriptor::Initialize(mitk::PixelType &type, size_t numOfElements, bool allocate) { if( m_PixelType.GetPixelTypeId() != type.GetPixelTypeId() ) { MITK_WARN << "Changing pixel type for channel: " << m_PixelType.GetItkTypeAsString() << " -> " << type.GetItkTypeAsString(); } m_PixelType = type; m_Size = numOfElements * m_PixelType.GetSize(); if( allocate ) { this->AllocateData(); } } */ void mitk::ChannelDescriptor::AllocateData() { if( m_Data == NULL) { m_Data = mitk::MemoryUtilities::AllocateElements( m_Size ); } } diff --git a/Core/Code/DataManagement/mitkImageDescriptor.cpp b/Core/Code/DataManagement/mitkImageDescriptor.cpp index 0cd62854d7..d61d758fea 100644 --- a/Core/Code/DataManagement/mitkImageDescriptor.cpp +++ b/Core/Code/DataManagement/mitkImageDescriptor.cpp @@ -1,105 +1,120 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkImageDescriptor.h" mitk::ImageDescriptor::ImageDescriptor() { //initialize the dimensions array for(unsigned int i=0; im_NumberOfChannels = 0; } // FIXME manage memory flag void mitk::ImageDescriptor::AddNewChannel(mitk::PixelType ptype, const char *name) { size_t elems = 1; for( unsigned int i=0; im_NumberOfDimensions; i++) elems *= this->m_Dimensions[i]; mitk::ChannelDescriptor desc(ptype, elems); this->m_ChannelDesc.push_back( desc ); if( name == 0) m_ChannelNames.push_back( "Unnamed ["+ptype.GetItkTypeAsString()+"]"); else m_ChannelNames.push_back(name); this->m_NumberOfChannels++; return; } void mitk::ImageDescriptor::Initialize(const ImageDescriptor::Pointer refDescriptor, unsigned int channel) { // initialize the members holding dimension information this->m_NumberOfChannels = refDescriptor->GetNumberOfChannels(); this->m_NumberOfDimensions = refDescriptor->GetNumberOfDimensions(); const unsigned int *refDims = refDescriptor->GetDimensions(); // copy the dimension information for( unsigned int i=0; i< this->m_NumberOfDimensions; i++) { this->m_Dimensions[i] = refDims[i]; } // get the channel descriptor and store them and so the name of the channel mitk::ChannelDescriptor desc = refDescriptor->GetChannelDescriptor(channel); this->m_ChannelDesc.push_back( desc ); this->m_ChannelNames.push_back( refDescriptor->GetChannelName(channel) ); } void mitk::ImageDescriptor::Initialize(const unsigned int *dims, const unsigned int dim) { this->m_NumberOfDimensions = dim; // copy the dimension information for( unsigned int i=0; i< this->m_NumberOfDimensions; i++) { this->m_Dimensions[i] = dims[i]; } } mitk::ChannelDescriptor mitk::ImageDescriptor::GetChannelDescriptor(unsigned int id) const { return this->m_ChannelDesc[id]; } mitk::PixelType mitk::ImageDescriptor::GetChannelTypeByName(const char *name) const { unsigned int idFound = 0; const std::string search_str(name); for( ConstChannelNamesIter iter = this->m_ChannelNames.begin(); iter < this->m_ChannelNames.end(); iter++) { if( search_str.compare( *iter ) ) idFound = iter - this->m_ChannelNames.begin(); } return (m_ChannelDesc[idFound]).GetPixelType(); } mitk::PixelType mitk::ImageDescriptor::GetChannelTypeById(const unsigned int id) const { if( id > this->m_NumberOfChannels ) { throw std::invalid_argument("The given id exceeds the number of active channel."); } else { mitk::ChannelDescriptor refDesc = this->m_ChannelDesc[id]; return refDesc.GetPixelType();// } } const std::string mitk::ImageDescriptor::GetChannelName(unsigned int id) const { if( id > this->m_ChannelNames.size() ) return "Out-of-range-access"; else return this->m_ChannelNames.at( id ); } diff --git a/Core/Code/DataManagement/mitkImageStatisticsHolder.cpp b/Core/Code/DataManagement/mitkImageStatisticsHolder.cpp index 1731b9e9b9..9188acb451 100644 --- a/Core/Code/DataManagement/mitkImageStatisticsHolder.cpp +++ b/Core/Code/DataManagement/mitkImageStatisticsHolder.cpp @@ -1,254 +1,269 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkImageStatisticsHolder.h" #include "mitkHistogramGenerator.h" //#include "mitkImageTimeSelector.h" mitk::ImageStatisticsHolder::ImageStatisticsHolder( mitk::Image* image) : m_Image(image)/*, m_TimeSelectorForExtremaObject(NULL)*/ { m_CountOfMinValuedVoxels.resize(1, 0); m_CountOfMaxValuedVoxels.resize(1, 0); m_ScalarMin.resize(1, itk::NumericTraits::max()); m_ScalarMax.resize(1, itk::NumericTraits::NonpositiveMin()); m_Scalar2ndMin.resize(1, itk::NumericTraits::max()); m_Scalar2ndMax.resize(1, itk::NumericTraits::NonpositiveMin()); mitk::HistogramGenerator::Pointer generator = mitk::HistogramGenerator::New(); m_HistogramGeneratorObject = generator; //m_Image = image; // create time selector //this->GetTimeSelector(); } mitk::ImageStatisticsHolder::~ImageStatisticsHolder() { m_HistogramGeneratorObject = NULL; //m_TimeSelectorForExtremaObject = NULL; //m_Image = NULL; } const mitk::ImageStatisticsHolder::HistogramType* mitk::ImageStatisticsHolder::GetScalarHistogram(int t) { mitk::ImageTimeSelector* timeSelector = this->GetTimeSelector(); if(timeSelector!=NULL) { timeSelector->SetTimeNr(t); timeSelector->UpdateLargestPossibleRegion(); mitk::HistogramGenerator* generator = static_cast(m_HistogramGeneratorObject.GetPointer()); generator->SetImage(timeSelector->GetOutput()); generator->ComputeHistogram(); return static_cast(generator->GetHistogram()); } return NULL; } bool mitk::ImageStatisticsHolder::IsValidTimeStep( int t) const { return m_Image->IsValidTimeStep(t); } mitk::ImageTimeSelector::Pointer mitk::ImageStatisticsHolder::GetTimeSelector() { //if(m_TimeSelectorForExtremaObject.IsNull()) //{ // m_TimeSelectorForExtremaObject = ImageTimeSelector::New(); ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();//static_cast( m_TimeSelectorForExtremaObject.GetPointer() ); timeSelector->SetInput(m_Image); //} return timeSelector; //static_cast( m_TimeSelectorForExtremaObject.GetPointer() ); } void mitk::ImageStatisticsHolder::Expand( unsigned int timeSteps ) { if(! m_Image->IsValidTimeStep(timeSteps - 1) ) return; // The BaseData needs to be expanded, call the mitk::Image::Expand() method m_Image->Expand(timeSteps); if(timeSteps > m_ScalarMin.size() ) { m_ScalarMin.resize(timeSteps, itk::NumericTraits::max()); m_ScalarMax.resize(timeSteps, itk::NumericTraits::NonpositiveMin()); m_Scalar2ndMin.resize(timeSteps, itk::NumericTraits::max()); m_Scalar2ndMax.resize(timeSteps, itk::NumericTraits::NonpositiveMin()); m_CountOfMinValuedVoxels.resize(timeSteps, 0); m_CountOfMaxValuedVoxels.resize(timeSteps, 0); } } void mitk::ImageStatisticsHolder::ResetImageStatistics() { m_ScalarMin.assign(1, itk::NumericTraits::max()); m_ScalarMax.assign(1, itk::NumericTraits::NonpositiveMin()); m_Scalar2ndMin.assign(1, itk::NumericTraits::max()); m_Scalar2ndMax.assign(1, itk::NumericTraits::NonpositiveMin()); m_CountOfMinValuedVoxels.assign(1, 0); m_CountOfMaxValuedVoxels.assign(1, 0); } #include "mitkImageAccessByItk.h" //#define BOUNDINGOBJECT_IGNORE template < typename ItkImageType > void mitk::_ComputeExtremaInItkImage( const ItkImageType* itkImage, mitk::ImageStatisticsHolder* statisticsHolder, int t) { typename ItkImageType::RegionType region; region = itkImage->GetBufferedRegion(); if(region.Crop(itkImage->GetRequestedRegion()) == false) return; if(region != itkImage->GetRequestedRegion()) return; itk::ImageRegionConstIterator it(itkImage, region); typedef typename ItkImageType::PixelType TPixel; TPixel value = 0; if ( statisticsHolder == NULL || !statisticsHolder->IsValidTimeStep( t ) ) return; statisticsHolder->Expand(t+1); // make sure we have initialized all arrays statisticsHolder->m_CountOfMinValuedVoxels[t] = 0; statisticsHolder->m_CountOfMaxValuedVoxels[t] = 0; statisticsHolder->m_Scalar2ndMin[t]= statisticsHolder->m_ScalarMin[t] = itk::NumericTraits::max(); statisticsHolder->m_Scalar2ndMax[t]= statisticsHolder->m_ScalarMax[t] = itk::NumericTraits::NonpositiveMin(); while( !it.IsAtEnd() ) { value = it.Get(); // if ( (value > mitkImage->m_ScalarMin) && (value < mitkImage->m_Scalar2ndMin) ) mitkImage->m_Scalar2ndMin = value; // else if ( (value < mitkImage->m_ScalarMax) && (value > mitkImage->m_Scalar2ndMax) ) mitkImage->m_Scalar2ndMax = value; // else if (value > mitkImage->m_ScalarMax) mitkImage->m_ScalarMax = value; // else if (value < mitkImage->m_ScalarMin) mitkImage->m_ScalarMin = value; // if numbers start with 2ndMin or 2ndMax and never have that value again, the previous above logic failed #ifdef BOUNDINGOBJECT_IGNORE if( value > -32765) { #endif // update min if ( value < statisticsHolder->m_ScalarMin[t] ) { statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMin[t]; statisticsHolder->m_ScalarMin[t] = value; statisticsHolder->m_CountOfMinValuedVoxels[t] = 1; } else if ( value == statisticsHolder->m_ScalarMin[t] ) { ++statisticsHolder->m_CountOfMinValuedVoxels[t]; } else if ( value < statisticsHolder->m_Scalar2ndMin[t] ) { statisticsHolder->m_Scalar2ndMin[t] = value; } // update max if ( value > statisticsHolder->m_ScalarMax[t] ) { statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_ScalarMax[t]; statisticsHolder->m_ScalarMax[t] = value; statisticsHolder->m_CountOfMaxValuedVoxels[t] = 1; } else if ( value == statisticsHolder->m_ScalarMax[t] ) { ++statisticsHolder->m_CountOfMaxValuedVoxels[t]; } else if ( value > statisticsHolder->m_Scalar2ndMax[t] ) { statisticsHolder->m_Scalar2ndMax[t] = value; } #ifdef BOUNDINGOBJECT_IGNORE } #endif ++it; } //// guard for wrong 2dMin/Max on single constant value images if (statisticsHolder->m_ScalarMax[t] == statisticsHolder->m_ScalarMin[t]) { statisticsHolder->m_Scalar2ndMax[t] = statisticsHolder->m_Scalar2ndMin[t] = statisticsHolder->m_ScalarMax[t]; } statisticsHolder->m_LastRecomputeTimeStamp.Modified(); //MITK_DEBUG <<"extrema "<::NonpositiveMin()<<" "<m_ScalarMin<<" "<m_Scalar2ndMin<<" "<m_Scalar2ndMax<<" "<m_ScalarMax<<" "<::max(); } void mitk::ImageStatisticsHolder::ComputeImageStatistics(int t) { // timestep valid? if (!m_Image->IsValidTimeStep(t)) return; // image modified? if (this->m_Image->GetMTime() > m_LastRecomputeTimeStamp.GetMTime()) this->ResetImageStatistics(); Expand(t+1); // do we have valid information already? if( m_ScalarMin[t] != itk::NumericTraits::max() || m_Scalar2ndMin[t] != itk::NumericTraits::max() ) return; // Values already calculated before... const mitk::PixelType pType = m_Image->GetPixelType(0); if(pType.GetNumberOfComponents() == 1) { // recompute mitk::ImageTimeSelector::Pointer timeSelector = this->GetTimeSelector(); if(timeSelector.IsNotNull()) { timeSelector->SetTimeNr(t); timeSelector->UpdateLargestPossibleRegion(); mitk::Image* image = timeSelector->GetOutput(); AccessByItk_2( image, _ComputeExtremaInItkImage, this, t ); } } else if(pType.GetNumberOfComponents() > 1) { m_ScalarMin[t] = 0; m_ScalarMax[t] = 255; m_Scalar2ndMin[t] = 0; m_Scalar2ndMax[t] = 255; } } mitk::ScalarType mitk::ImageStatisticsHolder::GetScalarValueMin(int t) { ComputeImageStatistics(t); return m_ScalarMin[t]; } mitk::ScalarType mitk::ImageStatisticsHolder::GetScalarValueMax(int t) { ComputeImageStatistics(t); return m_ScalarMax[t]; } mitk::ScalarType mitk::ImageStatisticsHolder::GetScalarValue2ndMin(int t) { ComputeImageStatistics(t); return m_Scalar2ndMin[t]; } mitk::ScalarType mitk::ImageStatisticsHolder::GetScalarValue2ndMax(int t) { ComputeImageStatistics(t); return m_Scalar2ndMax[t]; } mitk::ScalarType mitk::ImageStatisticsHolder::GetCountOfMinValuedVoxels(int t) { ComputeImageStatistics(t); return m_CountOfMinValuedVoxels[t]; } mitk::ScalarType mitk::ImageStatisticsHolder::GetCountOfMaxValuedVoxels(int t) { ComputeImageStatistics(t); return m_CountOfMaxValuedVoxels[t]; } diff --git a/Core/Code/DataManagement/mitkImageStatisticsHolder.h b/Core/Code/DataManagement/mitkImageStatisticsHolder.h index 67bfa5bb94..01edecb0e3 100644 --- a/Core/Code/DataManagement/mitkImageStatisticsHolder.h +++ b/Core/Code/DataManagement/mitkImageStatisticsHolder.h @@ -1,147 +1,162 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKIMAGESTATISTICSHOLDER_H #define MITKIMAGESTATISTICSHOLDER_H #include #include "mitkImage.h" #include "mitkImageTimeSelector.h" #ifndef __itkHistogram_h #include #endif namespace mitk { /** @brief Class holding the statistics informations about a single mitk::Image This computation was previously directly included in the definition and implementation of the mitk::Image class but for having a clear interface, all statistics computation is moved to the ImageStatisticsHolder class. Each mitk::Image holds a normal pointer to its StatisticsHolder object. To get access to the methods, use the GetStatistics() method in mitk::Image class. */ class MITK_CORE_EXPORT ImageStatisticsHolder { public: /** Constructor */ ImageStatisticsHolder(mitk::Image* image); /** Desctructor */ virtual ~ImageStatisticsHolder(); typedef itk::Statistics::Histogram HistogramType; virtual const HistogramType* GetScalarHistogram(int t=0); //##Documentation //## \brief Get the minimum for scalar images virtual ScalarType GetScalarValueMin(int t=0); //##Documentation //## \brief Get the maximum for scalar images virtual ScalarType GetScalarValueMax(int t=0); //##Documentation //## \brief Get the second smallest value for scalar images virtual ScalarType GetScalarValue2ndMin(int t=0); //##Documentation //## \brief Get the smallest value for scalar images, but do not recompute it first virtual mitk::ScalarType GetScalarValueMinNoRecompute( unsigned int t = 0 ) const { if ( t < m_ScalarMin.size() ) return m_ScalarMin[t]; else return itk::NumericTraits::max(); } //##Documentation //## \brief Get the second smallest value for scalar images, but do not recompute it first virtual mitk::ScalarType GetScalarValue2ndMinNoRecompute( unsigned int t = 0 ) const { if ( t < m_Scalar2ndMin.size() ) return m_Scalar2ndMin[t]; else return itk::NumericTraits::max(); } //##Documentation //## \brief Get the second largest value for scalar images virtual ScalarType GetScalarValue2ndMax(int t=0); //##Documentation //## \brief Get the largest value for scalar images, but do not recompute it first virtual mitk::ScalarType GetScalarValueMaxNoRecompute( unsigned int t = 0 ) { if ( t < m_ScalarMax.size() ) return m_ScalarMax[t]; else return itk::NumericTraits::NonpositiveMin(); } //##Documentation //## \brief Get the second largest value for scalar images, but do not recompute it first virtual mitk::ScalarType GetScalarValue2ndMaxNoRecompute( unsigned int t = 0 ) { if ( t < m_Scalar2ndMax.size() ) return m_Scalar2ndMax[t]; else return itk::NumericTraits::NonpositiveMin(); } //##Documentation //## \brief Get the count of voxels with the smallest scalar value in the dataset mitk::ScalarType GetCountOfMinValuedVoxels(int t = 0); //##Documentation //## \brief Get the count of voxels with the largest scalar value in the dataset mitk::ScalarType GetCountOfMaxValuedVoxels(int t = 0); //##Documentation //## \brief Get the count of voxels with the largest scalar value in the dataset virtual unsigned int GetCountOfMaxValuedVoxelsNoRecompute( unsigned int t = 0 ) { if ( t < m_CountOfMaxValuedVoxels.size() ) return m_CountOfMaxValuedVoxels[t]; else return 0; } //##Documentation //## \brief Get the count of voxels with the smallest scalar value in the dataset virtual unsigned int GetCountOfMinValuedVoxelsNoRecompute( unsigned int t = 0 ) const { if ( t < m_CountOfMinValuedVoxels.size() ) return m_CountOfMinValuedVoxels[t]; else return 0; } bool IsValidTimeStep( int t) const; template < typename ItkImageType > friend void _ComputeExtremaInItkImage( const ItkImageType* itkImage, mitk::ImageStatisticsHolder* statisticsHolder, int t); protected: virtual void ResetImageStatistics(); virtual void ComputeImageStatistics(int t=0); virtual void Expand( unsigned int timeSteps ); ImageTimeSelector::Pointer GetTimeSelector(); mitk::Image* m_Image; mutable itk::Object::Pointer m_HistogramGeneratorObject; mutable itk::Object::Pointer m_TimeSelectorForExtremaObject; mutable std::vector m_CountOfMinValuedVoxels; mutable std::vector m_CountOfMaxValuedVoxels; mutable std::vector m_ScalarMin; mutable std::vector m_ScalarMax; mutable std::vector m_Scalar2ndMin; mutable std::vector m_Scalar2ndMax; itk::TimeStamp m_LastRecomputeTimeStamp; }; } //end namespace #endif // MITKIMAGESTATISTICSHOLDER_H diff --git a/Core/Code/IO/mitkPixelTypeMultiplex.h b/Core/Code/IO/mitkPixelTypeMultiplex.h index 27bf024196..07c1e55298 100644 --- a/Core/Code/IO/mitkPixelTypeMultiplex.h +++ b/Core/Code/IO/mitkPixelTypeMultiplex.h @@ -1,126 +1,141 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPIXELTYPEMULTIPLEX_H #define MITKPIXELTYPEMULTIPLEX_H #define mitkPixelTypeMultiplex0( function, ptype ) \ { \ if ( ptype.GetTypeId() == typeid(char) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(unsigned char))\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(short) )\ function( ptype, ); \ else if ( ptype.GetTypeId() == typeid(unsigned short) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(int) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(unsigned int) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(long int) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(unsigned long int) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(float) )\ function( ptype, );\ else if ( ptype.GetTypeId() == typeid(double) )\ function( ptype, );\ }\ #define mitkPixelTypeMultiplex1( function, ptype, param1 ) \ { \ if ( ptype.GetTypeId() == typeid(char) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(unsigned char))\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(short) )\ function( ptype, param1 ); \ else if ( ptype.GetTypeId() == typeid(unsigned short) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(int) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(unsigned int) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(long int) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(unsigned long int) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(float) )\ function( ptype, param1 );\ else if ( ptype.GetTypeId() == typeid(double) )\ function( ptype, param1 );\ }\ #define mitkPixelTypeMultiplex2( function, ptype, param1, param2 ) \ { \ if ( ptype.GetTypeId() == typeid(char) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(unsigned char))\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(short) )\ function( ptype, param1, param2 ); \ else if ( ptype.GetTypeId() == typeid(unsigned short) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(int) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(unsigned int) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(long int) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(unsigned long int) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(float) )\ function( ptype, param1, param2 );\ else if ( ptype.GetTypeId() == typeid(double) )\ function( ptype, param1, param2 );\ }\ #define mitkPixelTypeMultiplex3( function, ptype, param1, param2, param3 ) \ { \ if ( ptype.GetTypeId() == typeid(char) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(unsigned char))\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(short) )\ function( ptype, param1, param2, param3 ); \ else if ( ptype.GetTypeId() == typeid(unsigned short) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(int) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(unsigned int) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(long int) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(unsigned long int) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(float) )\ function( ptype, param1, param2, param3 );\ else if ( ptype.GetTypeId() == typeid(double) )\ function( ptype, param1, param2, param3 );\ }\ #define mitkPixelTypeMultiplex4( function, ptype, param1, param2, param3, param4 ) \ { \ if ( ptype.GetTypeId() == typeid(char) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(unsigned char))\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(short) )\ function( ptype, param1, param2, param3, param4 ); \ else if ( ptype.GetTypeId() == typeid(unsigned short) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(int) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(unsigned int) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(long int) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(unsigned long int) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(float) )\ function( ptype, param1, param2, param3, param4 );\ else if ( ptype.GetTypeId() == typeid(double) )\ function( ptype, param1, param2, param3, param4 );\ }\ #endif // MITKPIXELTYPEMULTIPLEX_H diff --git a/Core/Code/Interactions/mitkCrosshairPositionEvent.cpp b/Core/Code/Interactions/mitkCrosshairPositionEvent.cpp index 33d5aabee3..64e59aa81d 100644 --- a/Core/Code/Interactions/mitkCrosshairPositionEvent.cpp +++ b/Core/Code/Interactions/mitkCrosshairPositionEvent.cpp @@ -1,8 +1,23 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkCrosshairPositionEvent.h" mitk::CrosshairPositionEvent::CrosshairPositionEvent( BaseRenderer* sender) : Event( sender, 0, 0, 0, 0) { } diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp index 433015b7b4..733ea11d13 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -1,1248 +1,969 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //MITK #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include "mitkImageStatisticsHolder.h" //MITK Rendering #include "mitkImageVtkMapper2D.h" #include "vtkMitkThickSlicesFilter.h" #include "vtkMitkApplyLevelWindowToRGBFilter.h" //VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ITK #include mitk::ImageVtkMapper2D::ImageVtkMapper2D() { } mitk::ImageVtkMapper2D::~ImageVtkMapper2D() { //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event, //in order to delete the images from the 3D RW. this->InvokeEvent( itk::DeleteEvent() ); } //set the two points defining the textured plane according to the dimension and spacing void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + float depth = this->CalculateLayerDepth(renderer); //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct //plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); //These two points define the axes of the plane in combination with the origin. //Point 1 is the x-axis and point 2 the y-axis. //Each plane is transformed according to the view (transversal, coronal and saggital) afterwards. - localStorage->m_Plane->SetPoint1(planeBounds[1], planeBounds[2], depth); //P1: (xMax, yMin, depth) + localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) } float mitk::ImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) { //get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined float depth = -maxRange*0.01; // divide by 100 int layer = 0; GetDataNode()->GetIntProperty( "layer", layer, renderer); //add the layer property for each image to render images with a higher layer on top of the others depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) if(depth > 0.0f) { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } const mitk::Image* mitk::ImageVtkMapper2D::GetInput( void ) { return static_cast< const mitk::Image * >( this->GetData() ); } vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actor; } void mitk::ImageVtkMapper2D::MitkRenderOverlay(BaseRenderer* renderer) { if ( this->IsVisible(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } void mitk::ImageVtkMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) { if ( this->IsVisible( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } void mitk::ImageVtkMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) { if ( this->IsVisible(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } } void mitk::ImageVtkMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) { if(IsVisible(renderer)==false) return; if ( GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); } } void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); if ( input == NULL || input->IsInitialized() == false ) { return; } //check if there is a valid worldGeometry const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) { return; } - // check if there is something to display - if ( !input->IsVolumeSet( this->GetTimestep() ) ) return; - input->Update(); - vtkImageData* inputData = input->GetVtkImageData( this->GetTimestep() ); - if ( inputData == NULL ) - { - return; - } - - // how big the area is in physical coordinates: widthInMM x heightInMM pixels - mitk::ScalarType widthInMM, heightInMM; - - // take transform of input image into account - const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); - const Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( this->GetTimestep() ); - - // Bounds information for reslicing (only reuqired if reference geometry - // is present) - vtkFloatingPointType sliceBounds[6]; - bool boundsInitialized = false; - for ( int i = 0; i < 6; ++i ) - { - sliceBounds[i] = 0.0; - } - - //Extent (in pixels) of the image - Vector2D extent; - - // Do we have a simple PlaneGeometry? - // This is the "regular" case (e.g. slicing through an image axis-parallel or even oblique) - const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); - if ( planeGeometry != NULL ) - { - localStorage->m_Origin = planeGeometry->GetOrigin(); - localStorage->m_Right = planeGeometry->GetAxisVector( 0 ); // right = Extent of Image in mm (worldspace) - localStorage->m_Bottom = planeGeometry->GetAxisVector( 1 ); - localStorage->m_Normal = planeGeometry->GetNormal(); - - bool inPlaneResampleExtentByGeometry = false; - GetDataNode()->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); - - if ( inPlaneResampleExtentByGeometry ) - { - // Resampling grid corresponds to the current world geometry. This - // means that the spacing of the output 2D image depends on the - // currently selected world geometry, and *not* on the image itself. - extent[0] = worldGeometry->GetExtent( 0 ); - extent[1] = worldGeometry->GetExtent( 1 ); - } - else - { - // Resampling grid corresponds to the input geometry. This means that - // the spacing of the output 2D image is directly derived from the - // associated input image, regardless of the currently selected world - // geometry. - Vector3D rightInIndex, bottomInIndex; - inputGeometry->WorldToIndex( localStorage->m_Right, rightInIndex ); - inputGeometry->WorldToIndex( localStorage->m_Bottom, bottomInIndex ); - extent[0] = rightInIndex.GetNorm(); - extent[1] = bottomInIndex.GetNorm(); - } - - // Get the extent of the current world geometry and calculate resampling - // spacing therefrom. - widthInMM = worldGeometry->GetExtentInMM( 0 ); - heightInMM = worldGeometry->GetExtentInMM( 1 ); - - localStorage->m_mmPerPixel[0] = widthInMM / extent[0]; - localStorage->m_mmPerPixel[1] = heightInMM / extent[1]; - - localStorage->m_Right.Normalize(); - localStorage->m_Bottom.Normalize(); - localStorage->m_Normal.Normalize(); - - //transform the origin to corner based coordinates, because VTK is corner based. - localStorage->m_Origin += localStorage->m_Right * ( localStorage->m_mmPerPixel[0] * 0.5 ); - localStorage->m_Origin += localStorage->m_Bottom * ( localStorage->m_mmPerPixel[1] * 0.5 ); - - // Use inverse transform of the input geometry for reslicing the 3D image - localStorage->m_Reslicer->SetResliceTransform( - inputGeometry->GetVtkTransform()->GetLinearInverse() ); - - // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) - localStorage->m_Reslicer->SetBackgroundLevel( -32768 ); - - // Calculate the actual bounds of the transformed plane clipped by the - // dataset bounding box; this is required for drawing the texture at the - // correct position during 3D mapping. - if (worldGeometry->HasReferenceGeometry()) - { - boundsInitialized = this->CalculateClippedPlaneBounds( - worldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds ); - } - } - else - { - // Do we have an AbstractTransformGeometry? - // This is the case for AbstractTransformGeometry's (e.g. a thin-plate-spline transform) - const mitk::AbstractTransformGeometry* abstractGeometry = - dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); - - if(abstractGeometry != NULL) - { - - extent[0] = abstractGeometry->GetParametricExtent(0); - extent[1] = abstractGeometry->GetParametricExtent(1); - widthInMM = abstractGeometry->GetParametricExtentInMM(0); - heightInMM = abstractGeometry->GetParametricExtentInMM(1); + //set main input for ExtractSliceFilter + localStorage->m_Reslicer->SetInput(input); + localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); + localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); - localStorage->m_mmPerPixel[0] = widthInMM / extent[0]; - localStorage->m_mmPerPixel[1] = heightInMM / extent[1]; - localStorage->m_Origin = abstractGeometry->GetPlane()->GetOrigin(); + //set the transformation of the image to adapt reslice axis + localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeSlicedGeometry()->GetGeometry3D( this->GetTimestep() ) ); - localStorage->m_Right = abstractGeometry->GetPlane()->GetAxisVector(0); - localStorage->m_Right.Normalize(); - localStorage->m_Bottom = abstractGeometry->GetPlane()->GetAxisVector(1); - localStorage->m_Bottom.Normalize(); + //is the geometry of the slice based on the input image or the worldgeometry? + bool inPlaneResampleExtentByGeometry = false; + GetDataNode()->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); + localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); - localStorage->m_Normal = abstractGeometry->GetPlane()->GetNormal(); - localStorage->m_Normal.Normalize(); - // Use a combination of the InputGeometry *and* the possible non-rigid - // AbstractTransformGeometry for reslicing the 3D Image - vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); - composedResliceTransform->Identity(); - composedResliceTransform->Concatenate( - inputGeometry->GetVtkTransform()->GetLinearInverse() ); - composedResliceTransform->Concatenate( - abstractGeometry->GetVtkAbstractTransform() - ); - - localStorage->m_Reslicer->SetResliceTransform( composedResliceTransform ); - composedResliceTransform->UnRegister( NULL ); // decrease RC - - // Set background level to BLACK instead of translucent, to avoid - // boundary artifacts (see Geometry2DDataVtkMapper3D) - localStorage->m_Reslicer->SetBackgroundLevel( -1023 ); - } - else - { - //no geometry => we can't reslice - return; - } - } - - // Make sure that the image to display has a certain minimum size. - if ( (extent[0] <= 2) && (extent[1] <= 2) ) - { - return; - } - - //### begin set reslice interpolation // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) { VtkResliceInterpolationProperty *resliceInterpolationProperty; this->GetDataNode()->GetProperty( - resliceInterpolationProperty, "reslice interpolation" ); + resliceInterpolationProperty, "reslice interpolation" ); int interpolationMode = VTK_RESLICE_NEAREST; if ( resliceInterpolationProperty != NULL ) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } switch ( interpolationMode ) { case VTK_RESLICE_NEAREST: - localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor(); + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); break; case VTK_RESLICE_LINEAR: - localStorage->m_Reslicer->SetInterpolationModeToLinear(); + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); break; case VTK_RESLICE_CUBIC: - localStorage->m_Reslicer->SetInterpolationModeToCubic(); + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); break; } } else { - localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor(); + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } - //### end set reslice interpolation + + //set the vtk output property to true, makes sure that no unneeded mitk image convertion + //is done. + localStorage->m_Reslicer->SetVtkOutputRequest(true); + //Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; - // Thick slices parameters - if( inputData->GetNumberOfScalarComponents() == 1 ) // for now only single component are allowed + if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed { DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); if(dn) { ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=1; if(thickSlicesNum > 10) thickSlicesNum=10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } - localStorage->m_UnitSpacingImageFilter->SetInput( inputData ); - localStorage->m_Reslicer->SetInput( localStorage->m_UnitSpacingImageFilter->GetOutput() ); - - //number of pixels per mm in x- and y-direction of the resampled - Vector2D pixelsPerMM; - pixelsPerMM[0] = 1.0 / localStorage->m_mmPerPixel[0]; - pixelsPerMM[1] = 1.0 / localStorage->m_mmPerPixel[1]; - - //calulate the originArray and the orientations for the reslice-filter - double originArray[3]; - itk2vtk( localStorage->m_Origin, originArray ); - - localStorage->m_Reslicer->SetResliceAxesOrigin( originArray ); - - double cosines[9]; - // direction of the X-axis of the sampled result - vnl2vtk( localStorage->m_Right.Get_vnl_vector(), cosines ); - // direction of the Y-axis of the sampled result - vnl2vtk( localStorage->m_Bottom.Get_vnl_vector(), cosines + 3 );//fill next 3 elements - // normal of the plane - vnl2vtk( localStorage->m_Normal.Get_vnl_vector(), cosines + 6 );//fill the last 3 elements - - localStorage->m_Reslicer->SetResliceAxesDirectionCosines( cosines ); - - int xMin, xMax, yMin, yMax; - if ( boundsInitialized ) - { - // Calculate output extent (integer values) - xMin = static_cast< int >( sliceBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); - xMax = static_cast< int >( sliceBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); - yMin = static_cast< int >( sliceBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); - yMax = static_cast< int >( sliceBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); - } - else - { - // If no reference geometry is available, we also don't know about the - // maximum plane size; - xMin = yMin = 0; - xMax = static_cast< int >( extent[0] - - pixelsPerMM[0] + 0.5); - yMax = static_cast< int >( extent[1] - - pixelsPerMM[1] + 0.5); - } - - // Disallow huge dimensions - if ( (xMax-xMin) * (yMax-yMin) > 4096*4096 ) - { - return; - } - // Calculate dataset spacing in plane z direction (NOT spacing of current - // world geometry) - double dataZSpacing = 1.0; + if(thickSlicesMode > 0) + { + double dataZSpacing = 1.0; + + Vector3D normInIndex, normal; + const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); + if ( planeGeometry != NULL ){ + normal = planeGeometry->GetNormal(); + }else{ + const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); + if(abstractGeometry != NULL) + normal = abstractGeometry->GetPlane()->GetNormal(); + else + return; //no fitting geometry set + } + normal.Normalize(); - Vector3D normInIndex; - inputGeometry->WorldToIndex( localStorage->m_Normal, normInIndex ); + input->GetTimeSlicedGeometry()->GetGeometry3D( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); - if(thickSlicesMode > 0) - { dataZSpacing = 1.0 / normInIndex.GetNorm(); + localStorage->m_Reslicer->SetOutputDimensionality( 3 ); - localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, -thickSlicesNum, 0+thickSlicesNum ); - } - else - { - localStorage->m_Reslicer->SetOutputDimensionality( 2 ); - localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 0 ); - } + localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); + localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); - localStorage->m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); - localStorage->m_Reslicer->SetOutputSpacing( localStorage->m_mmPerPixel[0], localStorage->m_mmPerPixel[1], dataZSpacing ); - // xMax and yMax are meant exclusive until now, whereas - // SetOutputExtent wants an inclusive bound. Thus, we need - // to subtract 1. - - //Make sure the updateExtent is equal to the wholeExtent of vtkImageReslice, - //else the updateExtent is one step ahead of the wholeExtent and vtk errors - //are thrown. - localStorage->m_Reslicer->UpdateWholeExtent(); - - // Do the reslicing. Modified() is called to make sure that the reslicer is - // executed even though the input geometry information did not change; this - // is necessary when the input /em data, but not the /em geometry changes. - if(thickSlicesMode>0) - { + // Do the reslicing. Modified() is called to make sure that the reslicer is + // executed even though the input geometry information did not change; this + // is necessary when the input /em data, but not the /em geometry changes. localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); - localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetOutput() ); + localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetVtkOutput() ); + + //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually + localStorage->m_Reslicer->Modified(); + localStorage->m_Reslicer->Update(); + localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { + //this is needed when thick mode was enable bevore. These variable have to be reset to default values + localStorage->m_Reslicer->SetOutputDimensionality( 2 ); + localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); + localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); + + localStorage->m_Reslicer->Modified(); - localStorage->m_Reslicer->Update(); - localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetOutput(); + //start the pipeline with updating the largest possible, needed if the geometry of the input has changed + localStorage->m_Reslicer->UpdateLargestPossibleRegion(); + localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } - if((localStorage->m_ReslicedImage == NULL) || (localStorage->m_ReslicedImage->GetDataDimension() < 1)) + + // Bounds information for reslicing (only reuqired if reference geometry + // is present) + //this used for generating a vtkPLaneSource with the right size + vtkFloatingPointType sliceBounds[6]; + for ( int i = 0; i < 6; ++i ) { - MITK_WARN << "reslicer returned empty image"; - return; + sliceBounds[i] = 0.0; } + localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); + + //get the spacing of the slice + localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); + //get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); //get the binary property bool binary = false; bool binaryOutline = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); if(binary) //binary image { this->GetDataNode()->GetBoolProperty( "outline binary", binaryOutline, renderer ); if(binaryOutline) //contour rendering { if ( this->GetInput()->GetPixelType().GetBpe() <= 8 ) { //generate ontours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "outline width", binaryOutlineWidth, renderer )) { localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth); } } else { binaryOutline = false; this->ApplyLookuptable(renderer); MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; } } else //standard binary image { if(numberOfComponents != 1) { MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!"; } } this->ApplyLookuptable(renderer); //Interpret the values as binary values localStorage->m_Texture->MapColorScalarsThroughLookupTableOn(); } else if( numberOfComponents == 1 ) //gray images { //Interpret the values as gray values localStorage->m_Texture->MapColorScalarsThroughLookupTableOn(); this->ApplyLookuptable(renderer); } else if ( (numberOfComponents == 3) || (numberOfComponents == 4) ) //RBG(A) images { //Interpret the RGB(A) images values correctly localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); this->ApplyLookuptable(renderer); this->ApplyRBGALevelWindow(renderer); } else { MITK_ERROR << "2D Reindering Error: Unknown number of components!!! Please report to rendering task force or check your data!"; } this->ApplyColor( renderer ); this->ApplyOpacity( renderer ); this->TransformActor( renderer ); //connect mapper with the data if(binary && binaryOutline) //connect the mapper with the polyData which contains the lines { //We need the contour for the binary oultine property as actor localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData); localStorage->m_Actor->SetTexture(NULL); //no texture for contours } else { //Connect the mapper with the input texture. This is the standard case. //setup the textured plane this->GeneratePlane( renderer, sliceBounds ); //set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); //set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); // check for interpolation properties bool textureInterpolation = false; GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); //set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); bool useColor = true; this->GetDataNode()->GetBoolProperty( "use color", useColor, renderer ); if( useColor ) { float rgb[3]= { 1.0f, 1.0f, 1.0f }; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); if(hover && !selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.hoveringcolor", renderer)); + ("binaryimage.hoveringcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetColor( rgb, renderer ); } } if(selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.selectedcolor", renderer)); + ("binaryimage.selectedcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetColor( rgb, renderer ); } } if(!hover && !selected) { GetColor( rgb, renderer ); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK localStorage->m_Actor->GetProperty()->SetColor(rgbConv); } else { //If the user defines a lut, we dont want to use the color and take white instead. localStorage->m_Actor->GetProperty()->SetColor(1.0, 1.0, 1.0); } } void mitk::ImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists GetOpacity( opacity, renderer ); //set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); } void mitk::ImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) { bool binary = false; bool CTFcanBeApplied = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); LocalStorage* localStorage = this->GetLocalStorage(renderer); float blackOpacity = 0.0; bool isBinary = false; bool foundBinaryProperty = false; foundBinaryProperty = this->GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if (foundBinaryProperty && !isBinary) { this->GetDataNode()->GetFloatProperty( "black opacity", blackOpacity, renderer); } localStorage->m_LookupTable->SetTableValue(0, 0.0, 0.0, 0.0, blackOpacity); //default lookuptable localStorage->m_Texture->SetLookupTable( localStorage->m_LookupTable ); if(binary) { //default lookuptable for binary images localStorage->m_Texture->GetLookupTable()->SetRange(0.0, 1.0); } else { bool useColor = true; this->GetDataNode()->GetBoolProperty( "use color", useColor, renderer ); if((!useColor)) { //BEGIN PROPERTY user-defined lut //currently we do not allow a lookuptable if it is a binary image // If lookup table use is requested... mitk::LookupTableProperty::Pointer LookupTableProp; LookupTableProp = dynamic_cast - (this->GetDataNode()->GetProperty("LookupTable")); + (this->GetDataNode()->GetProperty("LookupTable")); //...check if there is a lookuptable provided by the user if ( LookupTableProp.IsNotNull() ) { // If lookup table use is requested and supplied by the user: // only update the lut, when the properties have changed... if( LookupTableProp->GetLookupTable()->GetMTime() <= this->GetDataNode()->GetPropertyList()->GetMTime() ) - { + { LookupTableProp->GetLookupTable()->ChangeOpacityForAll( LookupTableProp->GetLookupTable()->GetVtkLookupTable()->GetAlpha()*localStorage->m_Actor->GetProperty()->GetOpacity() ); LookupTableProp->GetLookupTable()->ChangeOpacity(0, blackOpacity); } //we use the user-defined lookuptable localStorage->m_Texture->SetLookupTable( LookupTableProp->GetLookupTable()->GetVtkLookupTable() ); } else { CTFcanBeApplied = true; } }//END PROPERTY user-defined lut LevelWindow levelWindow; this->GetLevelWindow( levelWindow, renderer ); //set up the lookuptable with the level window range localStorage->m_Texture->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); } //the color function can be applied if the user does not want to use color //and does not provide a lookuptable if(CTFcanBeApplied) { ApplyColorTransferFunction(renderer); } localStorage->m_Texture->SetInput( localStorage->m_ReslicedImage ); } void mitk::ImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer* renderer) { mitk::TransferFunctionProperty::Pointer transferFunctionProperty = - dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); + dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); if(transferFunctionProperty.IsNotNull()) { localStorage->m_Texture->SetLookupTable(transferFunctionProperty->GetValue()->GetColorTransferFunction()); } else { MITK_WARN << "Neither a lookuptable nor a transfer function is set and use color is off."; } } -bool mitk::ImageVtkMapper2D::LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ) -{ - vtkFloatingPointType point1[3]; - vtkFloatingPointType point2[3]; - points->GetPoint( p1, point1 ); - points->GetPoint( p2, point2 ); - - if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) - { - double x, y; - x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); - y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); - - if ( x < bounds[0] ) { bounds[0] = x; } - if ( x > bounds[1] ) { bounds[1] = x; } - if ( y < bounds[2] ) { bounds[2] = y; } - if ( y > bounds[3] ) { bounds[3] = y; } - bounds[4] = bounds[5] = 0.0; - return true; - } - return false; -} - -bool mitk::ImageVtkMapper2D::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) -{ - // Clip the plane with the bounding geometry. To do so, the corner points - // of the bounding box are transformed by the inverse transformation - // matrix, and the transformed bounding box edges derived therefrom are - // clipped with the plane z=0. The resulting min/max values are taken as - // bounds for the image reslicer. - const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); - - mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); - mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); - - vtkSmartPointer points = vtkSmartPointer::New(); - if(boundingGeometry->GetImageGeometry()) - { - points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); - } - else - { - points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); - points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); - points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); - points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); - points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); - points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); - points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); - points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); - } - - vtkSmartPointer newPoints = vtkSmartPointer::New(); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Identity(); - transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); - - transform->Concatenate( boundingGeometry->GetVtkTransform() ); - - transform->TransformPoints( points, newPoints ); - bounds[0] = bounds[2] = 10000000.0; - bounds[1] = bounds[3] = -10000000.0; - bounds[4] = bounds[5] = 0.0; - - this->LineIntersectZero( newPoints, 0, 1, bounds ); - this->LineIntersectZero( newPoints, 1, 2, bounds ); - this->LineIntersectZero( newPoints, 2, 3, bounds ); - this->LineIntersectZero( newPoints, 3, 0, bounds ); - this->LineIntersectZero( newPoints, 0, 4, bounds ); - this->LineIntersectZero( newPoints, 1, 5, bounds ); - this->LineIntersectZero( newPoints, 2, 6, bounds ); - this->LineIntersectZero( newPoints, 3, 7, bounds ); - this->LineIntersectZero( newPoints, 4, 5, bounds ); - this->LineIntersectZero( newPoints, 5, 6, bounds ); - this->LineIntersectZero( newPoints, 6, 7, bounds ); - this->LineIntersectZero( newPoints, 7, 4, bounds ); - - if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) - || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) - { - return false; - } - else - { - // The resulting bounds must be adjusted by the plane spacing, since we - // we have so far dealt with index coordinates - const float *planeSpacing = planeGeometry->GetFloatSpacing(); - bounds[0] *= planeSpacing[0]; - bounds[1] *= planeSpacing[0]; - bounds[2] *= planeSpacing[1]; - bounds[3] *= planeSpacing[1]; - bounds[4] *= planeSpacing[2]; - bounds[5] *= planeSpacing[2]; - return true; - } -} void mitk::ImageVtkMapper2D::ApplyRBGALevelWindow( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); //pass the LuT to the RBG filter localStorage->m_LevelWindowToRGBFilterObject->SetLookupTable(localStorage->m_Texture->GetLookupTable()); mitk::LevelWindow opacLevelWindow; if( this->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) {//pass the opaque level window to the filter localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else {//no opaque level window localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(0.0); localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(255.0); } localStorage->m_LevelWindowToRGBFilterObject->SetInput(localStorage->m_ReslicedImage); //connect the texture with the output of the RGB filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowToRGBFilterObject->GetOutputPort()); } void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) { if ( !this->IsVisible( renderer ) ) { return; } mitk::Image* data = const_cast( this->GetInput() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( this->GetTimestep() ) ) ) - { + { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) - { + { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations node->AddProperty( "use color", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); std::string modality; if ( node->GetStringProperty( "dicom.series.Modality", modality ) ) { // modality provided by DICOM or other reader if ( modality == "PT") // NOT a typo, PT is the abbreviation for PET used in DICOM { node->SetProperty( "use color", mitk::BoolProperty::New( false ), renderer ); node->SetProperty( "opacity", mitk::FloatProperty::New( 0.5 ), renderer ); } } bool isBinaryImage(false); if ( ! node->GetBoolProperty("binary", isBinaryImage) ) { // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); sliceSelector->SetSliceNr(image->GetDimension(2)/2); sliceSelector->SetTimeNr(image->GetDimension(3)/2); sliceSelector->SetChannelNr(image->GetDimension(4)/2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) { minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ( minValue == maxValue ) { // centralSlice is strange, lets look at all data minValue = image->GetStatistics()->GetScalarValueMin(); maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); } // some more properties specific for a binary... if (isBinaryImage) { node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } else //...or image type object { node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "black opacity", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); } if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; if ( node->GetStringProperty( "dicom.voilut.WindowCenter", sLevel ) && node->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) ) - { + { float level = atof( sLevel.c_str() ); float window = atof( sWindow.c_str() ); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; if ( node->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries ) && node->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) ) - { + { float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? // might remedy some l/w widget challenges } else { contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback } contrast.SetLevelWindow( level, window); node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); } } if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) && image->GetPixelType().GetPixelTypeId() == typeid(itk::RGBAPixel)) - { + { mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->SetProperty( "opaclevelwindow", prop, renderer ); } if((overwrite) || (node->GetProperty("LookupTable", renderer)==NULL)) { // add a default rainbow lookup table for color mapping mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); vtkLut->SetHueRange(0.6667, 0.0); vtkLut->SetTableRange(0.0, 20.0); vtkLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty( "LookupTable", mitkLutProp ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } mitk::ImageVtkMapper2D::LocalStorage* mitk::ImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } vtkSmartPointer mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ){ LocalStorage* localStorage = this->GetLocalStorage(renderer); //get the min and max index values of each direction int* extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image int line = dims[0]; //how many pixels per line? int x = xMin; //pixel index x int y = yMin; //pixel index y char* currentPixel; - + //get the depth for each contour float depth = CalculateLayerDepth(renderer); vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points while (y <= yMax) { currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer(x, y, 0)); //if the current pixel value is set to something if ((currentPixel) && (*currentPixel != 0)) - { + { //check in which direction a line is necessary - //a line is added if the neighbor of the current pixel has the value 0 - //and if the pixel is located at the edge of the image + //a line is added if the neighbor of the current pixel has the value 0 + //and if the pixel is located at the edge of the image - //if vvvvv not the first line vvvvv + //if vvvvv not the first line vvvvv if (y > yMin && *(currentPixel-line) == 0) - { //x direction - bottom edge of the pixel + { //x direction - bottom edge of the pixel //add the 2 points vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); //add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv not the last line vvvvv + //if vvvvv not the last line vvvvv if (y < yMax && *(currentPixel+line) == 0) - { //x direction - top edge of the pixel + { //x direction - top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv not the first pixel vvvvv + //if vvvvv not the first pixel vvvvv if ( (x > xMin || y > yMin) && *(currentPixel-1) == 0) - { //y direction - left edge of the pixel + { //y direction - left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv not the last pixel vvvvv + //if vvvvv not the last pixel vvvvv if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) == 0) - { //y direction - right edge of the pixel + { //y direction - right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - /* now consider pixels at the edge of the image */ + /* now consider pixels at the edge of the image */ - //if vvvvv left edge of image vvvvv + //if vvvvv left edge of image vvvvv if (x == xMin) - { //draw left edge of the pixel + { //draw left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv right edge of image vvvvv + //if vvvvv right edge of image vvvvv if (x == xMax) - { //draw right edge of the pixel + { //draw right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv bottom edge of image vvvvv + //if vvvvv bottom edge of image vvvvv if (y == yMin) - { //draw bottom edge of the pixel + { //draw bottom edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } - //if vvvvv top edge of image vvvvv + //if vvvvv top edge of image vvvvv if (y == yMax) - { //draw top edge of the pixel + { //draw top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } }//end if currentpixel is set x++; if (x > xMax) - { //reached end of line + { //reached end of line x = xMin; y++; } }//end of while // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); return polyData; } void mitk::ImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get the transformation matrix of the reslicer in order to render the slice as transversal, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); //transform the plane/contour (the actual actor) to the corresponding view (transversal, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); //transform the origin to center based coordinates, because MITK is center based. localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); } mitk::ImageVtkMapper2D::LocalStorage::LocalStorage() { //Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New(); m_LookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); - m_Reslicer = vtkSmartPointer::New(); + m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); - m_UnitSpacingImageFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); //the following actions are always the same and thus can be performed //in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); - m_Reslicer->ReleaseDataFlagOn(); - - m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); //built a default lookuptable m_LookupTable->SetRampToLinear(); m_LookupTable->SetSaturationRange( 0.0, 0.0 ); m_LookupTable->SetHueRange( 0.0, 0.0 ); m_LookupTable->SetValueRange( 0.0, 1.0 ); m_LookupTable->Build(); //do not repeat the texture (the image) m_Texture->RepeatOff(); //set the mapper for the actor m_Actor->SetMapper(m_Mapper); //filter for RGB(A) images m_LevelWindowToRGBFilterObject = new vtkMitkApplyLevelWindowToRGBFilter(); } diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h index d9f2634d92..d0909d6b64 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.h +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h @@ -1,284 +1,267 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E #define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E //MITK #include //MITK Rendering #include "mitkBaseRenderer.h" #include "mitkVtkMapper2D.h" +#include "mitkExtractSliceFilter.h" //VTK #include class vtkActor; class vtkPolyDataMapper; class vtkPlaneSource; class vtkImageData; class vtkLookupTable; class vtkImageReslice; class vtkImageChangeInformation; class vtkPoints; class vtkMitkThickSlicesFilter; class vtkPolyData; class vtkMitkApplyLevelWindowToRGBFilter; namespace mitk { /** \brief Mapper to resample and display 2D slices of a 3D image. * * The following image gives a brief overview of the mapping and the involved parts. * * \image html imageVtkMapper2Darchitecture.png * * First, the image is resliced by means of vtkImageReslice. The volume image * serves as input to the mapper in addition to spatial placement of the slice and a few other * properties such as thick slices. This code was already present in the old version * (mitkImageMapperGL2D). * * Next, the obtained slice (m_ReslicedImage) is used to create a texture * (m_Texture) and a plane onto which the texture is rendered (m_Plane). For * mapping purposes, a vtkPolyDataMapper (m_Mapper) is utilized. Orthographic * projection is applied to create the effect of a 2D image. The mapper and the * texture are assigned to the actor (m_Actor) which is passed to the VTK rendering * pipeline via the method GetVtkProp(). * * In order to transform the textured plane to the correct position in space, the * same transformation as used for reslicing is applied to both the camera and the * vtkActor. All important steps are explained in more detail below. The resulting * 2D image (by reslicing the underlying 3D input image appropriately) can either * be directly rendered in a 2D view or just be calculated to be used later by another * rendering entity, e.g. in texture mapping in a 3D view. * * Properties that can be set for images and influence the imageMapper2D are: * * - \b "opacity": (FloatProperty) Opacity of the image * - \b "black opacity": (FloatProperty) The opacity of black (first index in lookup tables) * - \b "color": (ColorProperty) Color of the image * - \b "use color": (BoolProperty) Use the color of the image or not * - \b "binary": (BoolProperty) is the image a binary image or not * - \b "outline binary": (BoolProperty) show outline of the image or not * - \b "texture interpolation": (BoolProperty) texture interpolation of the image * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not * - \b "layer": (IntProperty) Layer of the image * - \b "volume annotation color": (ColorProperty) color of the volume annotation, TODO has to be reimplemented * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) unit is ml or cm3, TODO has to be reimplemented * The default properties are: * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) * - \b "black opacity", mitk::FloatProperty::New(0.0f), renderer, overwrite ) * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) * - \b "use color", mitk::BoolProperty::New( true ), renderer, overwrite ) * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) * - \b "bounding box", mitk::BoolProperty::New( false ) ) * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) * If the modality-property is set for an image, the mapper uses modality-specific default properties, * e.g. color maps, if they are defined. * \ingroup Mapper */ class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper2D { public: /** Standard class typedefs. */ mitkClassMacro( ImageVtkMapper2D,VtkMapper2D ); /** Method for creation through the object factory. */ itkNewMacro(Self); /** \brief Get the Image to map */ const mitk::Image *GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ /** * To render transveral, coronal, and sagittal, the mapper is called three times. * For performance reasons, the corresponding data for each view is saved in the * internal helper class LocalStorage. This allows rendering n views with just * 1 mitkMapper using n vtkMapper. * */ class MITK_CORE_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; /** \brief Current slice of a 2D render window. */ vtkSmartPointer m_ReslicedImage; /** \brief Plane on which the slice is rendered as texture. */ vtkSmartPointer m_Plane; /** \brief The texture which is used to render the current slice. */ vtkSmartPointer m_Texture; /** \brief The lookuptable for colors and level window */ vtkSmartPointer m_LookupTable; /** \brief The actual reslicer (one per renderer) */ - vtkSmartPointer m_Reslicer; - /** \brief Thickslices post filtering. */ - vtkSmartPointer m_TSFilter; - /** \brief Using unit spacing for resampling makes life easier TODO improve docu ...*/ - vtkSmartPointer m_UnitSpacingImageFilter; + mitk::ExtractSliceFilter::Pointer m_Reslicer; + /** \brief Filter for thick slices */ + vtkSmartPointer m_TSFilter; /** \brief PolyData object containg all lines/points needed for outlining the contour. This container is used to save a computed contour for the next rendering execution. For instance, if you zoom or pann, there is no need to recompute the contour. */ vtkSmartPointer m_OutlinePolyData; + /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; - /** \brief Origin of the 2D geometry. */ - mitk::Point3D m_Origin; - /** \brief Bottom end point of the y-axis of the 2D geometry. */ - mitk::Vector3D m_Bottom; - /** \brief Right end point of the x-axis of the 2D geometry. */ - mitk::Vector3D m_Right; - /** \brief Normal of the 2D geometry. */ - mitk::Vector3D m_Normal; /** \brief mmPerPixel relation between pixel and mm. (World spacing).*/ - mitk::ScalarType m_mmPerPixel[2]; + mitk::ScalarType* m_mmPerPixel; /** \brief This filter is used to apply the level window to RBG(A) images. */ vtkMitkApplyLevelWindowToRGBFilter* m_LevelWindowToRGBFilterObject; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: /** \brief Transforms the actor to the actual position in 3D. * \param renderer The current renderer corresponding to the render window. */ void TransformActor(mitk::BaseRenderer* renderer); /** \brief Generates a plane according to the size of the resliced image in milimeters. * * \image html texturedPlane.png * * In VTK a vtkPlaneSource is defined through three points. The origin and two * points defining the axes of the plane (see VTK documentation). The origin is * set to (xMin; yMin; Z), where xMin and yMin are the minimal bounds of the * resliced image in space. Z is relevant for blending and the layer property. * The center of the plane (C) is also the center of the view plane (cf. the image above). * * \note For the standard MITK view with three 2D render windows showing three * different slices, three such planes are generated. All these planes are generated * in the XY-plane (even if they depict a YZ-slice of the volume). * */ void GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]); /** \brief Generates a vtkPolyData object containing the outline of a given binary slice. \param binarySlice - The binary image slice. (Volumes are not supported.) \param mmPerPixel - Spacing of the binary image slice. Hence it's 2D, only in x/y-direction. \note This code has been taken from the deprecated library iil. */ vtkSmartPointer CreateOutlinePolyData(mitk::BaseRenderer* renderer); /** Default constructor */ ImageVtkMapper2D(); /** Default deconstructor */ virtual ~ImageVtkMapper2D(); /** \brief Does the actual resampling, without rendering the image yet. * All the data is generated inside this method. The vtkProp (or Actor) * is filled with content (i.e. the resliced image). * * After generation, a 4x4 transformation matrix(t) of the current slice is obtained * from the vtkResliceImage object via GetReslicesAxis(). This matrix is * applied to each textured plane (actor->SetUserTransform(t)) to transform everything * to the actual 3D position (cf. the following image). * * \image html cameraPositioning3D.png * */ virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); - /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ - bool LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ); - - /** \brief Calculate the bounding box of the resliced image. This is necessary for - arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) - will have a new bounding box, which needs to be calculated. */ - bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); /** \brief This method uses the vtkCamera clipping range and the layer property * to calcualte the depth of the object (e.g. image or contour). The depth is used * to keep the correct order for the final VTK rendering.*/ float CalculateLayerDepth(mitk::BaseRenderer* renderer); /** \brief This method applies a level window on RBG(A) images. * It should only be called for internally for RGB(A) images. */ void ApplyRBGALevelWindow( mitk::BaseRenderer* renderer ); /** \brief This method applies (or modifies) the lookuptable for all types of images. */ void ApplyLookuptable( mitk::BaseRenderer* renderer ); /** \brief This method applies a color transfer function, if no LookuptableProperty is set. Internally, a vtkColorTransferFunction is used. This is usefull for coloring continous images (e.g. float) */ void ApplyColorTransferFunction(mitk::BaseRenderer* renderer); /** \brief Set the color of the image/polydata */ void ApplyColor( mitk::BaseRenderer* renderer ); /** \brief Set the opacity of the actor. */ void ApplyOpacity( mitk::BaseRenderer* renderer ); }; } // namespace mitk #endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Testing/CMakeLists.txt b/Core/Code/Testing/CMakeLists.txt index e861b8996e..2eb2a32c77 100644 --- a/Core/Code/Testing/CMakeLists.txt +++ b/Core/Code/Testing/CMakeLists.txt @@ -1,47 +1,63 @@ MITK_CREATE_MODULE_TESTS(LABELS MITK-Core) # MITK_INSTALL_TARGETS(EXECUTABLES MitkTestDriver) mitkAddCustomModuleTest(mitkDICOMLocaleTest_spacingOk_CT mitkDICOMLocaleTest ${MITK_DATA_DIR}/spacing-ok-ct.dcm) mitkAddCustomModuleTest(mitkDICOMLocaleTest_spacingOk_MR mitkDICOMLocaleTest ${MITK_DATA_DIR}/spacing-ok-mr.dcm) mitkAddCustomModuleTest(mitkDICOMLocaleTest_spacingOk_SC mitkDICOMLocaleTest ${MITK_DATA_DIR}/spacing-ok-sc.dcm) mitkAddCustomModuleTest(mitkEventMapperTest_Test1And2 mitkEventMapperTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml) #mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest ${MITK_DATA_DIR}/Pic3D.pic.gz ${MITK_DATA_DIR}/BallBinary30x30x30.pic.gz) mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/BallBinary30x30x30.nrrd) mitkAddCustomModuleTest(mitkDataStorageTest_US4DCyl mitkDataStorageTest ${MITK_DATA_DIR}/US4DCyl.nrrd) mitkAddCustomModuleTest(mitkStateMachineFactoryTest_TestStateMachine1_2 mitkStateMachineFactoryTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml) mitkAddCustomModuleTest(mitkDicomSeriesReaderTest_CTImage mitkDicomSeriesReaderTest ${MITK_DATA_DIR}/TinyCTAbdomen) mitkAddCustomModuleTest(mitkPointSetReaderTest mitkPointSetReaderTest ${MITK_DATA_DIR}/PointSetReaderTestData.mps) mitkAddCustomModuleTest(mitkImageTest_4DImageData mitkImageTest ${MITK_DATA_DIR}/US4DCyl.nrrd) mitkAddCustomModuleTest(mitkImageTest_2D+tImageData mitkImageTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageTest ${MITK_DATA_DIR}/Pic3D.nrrd) mitkAddCustomModuleTest(mitkImageTest_brainImage mitkImageTest ${MITK_DATA_DIR}/brain.mhd) #mitkAddCustomModuleTest(mitkImageTest_color2DImage mitkImageTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg) if(MITK_ENABLE_GUI_TESTING) mitkAddCustomModuleTest(mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/rgbaImage640x480REF.png #corresponding reference screenshot ) +mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2DTest #test for standard Pic3D transversal slice + ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage + -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3d640x480REF.png #corresponding reference screenshot +) +mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2DColorTest #test for color property (=blue) Pic3D sagittal slice + ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage + -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dColorBlue640x480REF.png #corresponding reference screenshot +) +mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2DLevelWindowTest #test for levelwindow property (=blood) Pic3D sagittal slice + ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage + -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dLevelWindowBlood640x480REF.png #corresponding reference screenshot +) +mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dOpacity640x480 mitkImageVtkMapper2DOpacityTest #test for opacity (=0.5) Pic3D coronal slice + ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage + -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dOpacity640x480REF.png #corresponding reference screenshot +) endif() # see bug 9882 if(NOT APPLE) add_test(mitkPointSetLocaleTest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkPointSetLocaleTest ${MITK_DATA_DIR}/pointSet.mps) set_property(TEST mitkPointSetLocaleTest PROPERTY LABELS MITK-Core) endif() add_test(mitkImageWriterTest_nrrdImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg) add_test(mitkImageWriterTest_2DPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/Png2D-bw.png) set_property(TEST mitkImageWriterTest_nrrdImage PROPERTY LABELS MITK-Core) set_property(TEST mitkImageWriterTest_2DPNGImage PROPERTY LABELS MITK-Core) add_subdirectory(DICOMTesting) diff --git a/Core/Code/Testing/DICOMTesting/DumpDICOMMitkImage.cpp b/Core/Code/Testing/DICOMTesting/DumpDICOMMitkImage.cpp index a6f0d63b2b..029a99fc2b 100644 --- a/Core/Code/Testing/DICOMTesting/DumpDICOMMitkImage.cpp +++ b/Core/Code/Testing/DICOMTesting/DumpDICOMMitkImage.cpp @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkTestDICOMLoading.h" int main(int argc, char** argv) { mitk::TestDICOMLoading loader; mitk::TestDICOMLoading::StringContainer files; for (int arg = 1; arg < argc; ++arg) files.push_back( argv[arg] ); mitk::TestDICOMLoading::ImageList images = loader.LoadFiles(files); // combine individual dumps in a way that VerifyDICOMMitkImageDump is able to separate again. // I.e.: when changing this piece of code, always change VerifyDICOMMitkImageDump, too. unsigned int imageCounter(0); for ( mitk::TestDICOMLoading::ImageList::const_iterator imageIter = images.begin(); imageIter != images.end(); ++imageIter ) { std::cout << "-- Image " << ++imageCounter << "\n"; std::cout << loader.DumpImageInformation( *imageIter ) << "\n"; } } diff --git a/Core/Code/Testing/DICOMTesting/Testing/mitkDICOMTestingSanityTest.cpp b/Core/Code/Testing/DICOMTesting/Testing/mitkDICOMTestingSanityTest.cpp index bf7d5f3b41..c28bb0ad5f 100644 --- a/Core/Code/Testing/DICOMTesting/Testing/mitkDICOMTestingSanityTest.cpp +++ b/Core/Code/Testing/DICOMTesting/Testing/mitkDICOMTestingSanityTest.cpp @@ -1,54 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkTestDICOMLoading.h" #include "mitkTestingMacros.h" int mitkDICOMTestingSanityTest(int argc, char** const argv) { MITK_TEST_BEGIN("DICOMTestingSanity") mitk::TestDICOMLoading loader; mitk::TestDICOMLoading::StringContainer files; // adapt expectations depending on configuration std::string configuration = mitk::DicomSeriesReader::GetConfigurationString(); MITK_TEST_OUTPUT(<< "Configuration: " << configuration) /* MITK_TEST_CONDITION_REQUIRED( configuration.find( "GDCM_VERSION: 2." ) != std::string::npos, "Expect at least GDCM version 2" ) */ // load files from commandline unsigned int numberOfExpectedImages = 0; if (argc > 1) numberOfExpectedImages = atoi(argv[1]); for (int arg = 2; arg < argc; ++arg) files.push_back( argv[arg] ); // verify all files are DICOM for (mitk::TestDICOMLoading::StringContainer::const_iterator fileIter = files.begin(); fileIter != files.end(); ++fileIter) { MITK_TEST_CONDITION_REQUIRED( mitk::DicomSeriesReader::IsDicom(*fileIter) , *fileIter << " is recognized as loadable DICOM object" ) } // compare with expected number of images from commandline mitk::TestDICOMLoading::ImageList images = loader.LoadFiles(files); MITK_TEST_CONDITION_REQUIRED( images.size() == numberOfExpectedImages, "Loading " << files.size() << " files from commandline results in " << numberOfExpectedImages << " images (see test invocation)" ) // check dump equality (dumping image information must always equal itself) for ( mitk::TestDICOMLoading::ImageList::const_iterator imageIter = images.begin(); imageIter != images.end(); ++imageIter ) { const mitk::Image* image = *imageIter; MITK_TEST_CONDITION( loader.CompareImageInformationDumps( loader.DumpImageInformation(image), loader.DumpImageInformation(image) ) == true, "Image information dumping is able to reproduce its result." ) } MITK_TEST_END() } diff --git a/Core/Code/Testing/DICOMTesting/VerifyDICOMMitkImageDump.cpp b/Core/Code/Testing/DICOMTesting/VerifyDICOMMitkImageDump.cpp index 2bd6ee1746..12da7dfadd 100644 --- a/Core/Code/Testing/DICOMTesting/VerifyDICOMMitkImageDump.cpp +++ b/Core/Code/Testing/DICOMTesting/VerifyDICOMMitkImageDump.cpp @@ -1,107 +1,122 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkTestDICOMLoading.h" std::vector LoadDumps(const std::string& fileName) { std::vector separatedDumps; std::ifstream fileStream( fileName.c_str() ); std::string buffer; std::string line; while(fileStream){ std::getline(fileStream, line); if (line.find("-- Image ") == 0) { // separator: starts a new image block if ( !buffer.empty() ) { // unless this is the first block separatedDumps.push_back(buffer); buffer.clear(); } } else { buffer += line + "\n"; } } fileStream.close(); // eat last image dump if ( !buffer.empty() ) { separatedDumps.push_back(buffer); buffer.clear(); } return separatedDumps; } int main(int argc, char** argv) { /** Loads a list of DICOM images, compares generated mitk::Images against stored references. first argument: file with reference dumps following arguments: file names to load */ if (argc < 2) { MITK_ERROR << "Usage:"; MITK_ERROR << " " << argv[0] << " reference.dump file1 [file2 .. fileN]"; MITK_ERROR << " "; MITK_ERROR << " Loads all DICOM images in file1 to fileN as MITK images "; MITK_ERROR << " and compares loaded images against stored expectations (dumps)."; MITK_ERROR << " See also DumpDICOMMitkImage (generates dumps)"; return EXIT_FAILURE; } mitk::TestDICOMLoading loader; mitk::TestDICOMLoading::StringContainer files; // TODO load reference dumps // load from argv[1] // separate at "-- Image n" // store in an array of dumps std::vector expectedDumps = LoadDumps(argv[1]); for (int arg = 2; arg < argc; ++arg) files.push_back( argv[arg] ); mitk::TestDICOMLoading::ImageList images = loader.LoadFiles(files); unsigned int imageCounter(0); for ( mitk::TestDICOMLoading::ImageList::const_iterator imageIter = images.begin(); imageIter != images.end(); ++imageIter, ++imageCounter ) { std::string imageDump = loader.DumpImageInformation( *imageIter ); if (imageCounter >= expectedDumps.size()) { MITK_ERROR << "Loader produces more images than expected. Aborting after image " << (imageCounter-1); MITK_INFO << "Image " << imageCounter << " loaded as:\n" << imageDump; return EXIT_FAILURE; } bool loadedAsExpected = loader.CompareImageInformationDumps( expectedDumps[imageCounter], imageDump ); if (loadedAsExpected) { MITK_INFO << "Image " << imageCounter << " loads as expected."; } else { MITK_ERROR << "Image " << imageCounter << " did not load as expected."; MITK_INFO << "Expected: \n" << expectedDumps[imageCounter] << "\nGot:\n" << imageDump; return EXIT_FAILURE; } } return EXIT_SUCCESS; } diff --git a/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp index 6bed44a6cf..691d34c4bd 100644 --- a/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp +++ b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.cpp @@ -1,417 +1,432 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "mitkTestDICOMLoading.h" #include mitk::TestDICOMLoading::TestDICOMLoading() :m_PreviousCLocale(NULL) { } void mitk::TestDICOMLoading::SetDefaultLocale() { // remember old locale only once if (m_PreviousCLocale == NULL) { m_PreviousCLocale = setlocale(LC_NUMERIC, NULL); // set to "C" setlocale(LC_NUMERIC, "C"); m_PreviousCppLocale = std::cin.getloc(); std::locale l( "C" ); std::cin.imbue(l); std::cout.imbue(l); } } void mitk::TestDICOMLoading::ResetUserLocale() { if (m_PreviousCLocale) { setlocale(LC_NUMERIC, m_PreviousCLocale); std::cin.imbue(m_PreviousCppLocale); std::cout.imbue(m_PreviousCppLocale); m_PreviousCLocale = NULL; } } mitk::TestDICOMLoading::ImageList mitk::TestDICOMLoading::LoadFiles( const StringContainer& files ) { for (StringContainer::const_iterator iter = files.begin(); iter != files.end(); ++iter) { MITK_DEBUG << "File " << *iter; } ImageList result; DicomSeriesReader::UidFileNamesMap seriesInFiles = DicomSeriesReader::GetSeries( files ); // TODO sort series UIDs, implementation of map iterator might differ on different platforms (or verify this is a standard topic??) for (DicomSeriesReader::UidFileNamesMap::const_iterator seriesIter = seriesInFiles.begin(); seriesIter != seriesInFiles.end(); ++seriesIter) { StringContainer files = seriesIter->second; DataNode::Pointer node = DicomSeriesReader::LoadDicomSeries( files ); if (node.IsNotNull()) { Image::Pointer image = dynamic_cast( node->GetData() ); result.push_back( image ); } else { } } return result; } std::string mitk::TestDICOMLoading::TypeIDToString(const std::type_info& ti) { if (ti == typeid(unsigned char)) return "UCHAR"; else if (ti == typeid(char)) return "CHAR"; else if (ti == typeid(unsigned short)) return "USHORT"; else if (ti == typeid(short)) return "SHORT"; else if (ti == typeid(unsigned int)) return "UINT"; else if (ti == typeid(int)) return "INT"; else if (ti == typeid(long unsigned int)) return "ULONG"; else if (ti == typeid(long int)) return "LONG"; else if (ti == typeid(float)) return "FLOAT"; else if (ti == typeid(double)) return "DOUBLE"; else return "UNKNOWN"; } // add a line to stringstream result (see DumpImageInformation #define DumpLine(field, data) DumpILine(0, field, data) // add an indented(!) line to stringstream result (see DumpImageInformation #define DumpILine(indent, field, data) \ { \ std::string DumpLine_INDENT; DumpLine_INDENT.resize(indent, ' ' ); \ result << DumpLine_INDENT << field << ": " << data << "\n"; \ } std::string mitk::TestDICOMLoading::DumpImageInformation( const Image* image ) { std::stringstream result; if (image == NULL) return result.str(); SetDefaultLocale(); // basic image data DumpLine( "Pixeltype", TypeIDToString( (image->GetPixelType().GetTypeId()) )); DumpLine( "BitsPerPixel", image->GetPixelType().GetBpe() ); DumpLine( "Dimension", image->GetDimension() ); result << "Dimensions: "; for (unsigned int dim = 0; dim < image->GetDimension(); ++dim) result << image->GetDimension(dim) << " "; result << "\n"; // geometry data result << "Geometry: \n"; Geometry3D* geometry = image->GetGeometry(); if (geometry) { AffineTransform3D* transform = geometry->GetIndexToWorldTransform(); if (transform) { result << " " << "Matrix: "; const AffineTransform3D::MatrixType& matrix = transform->GetMatrix(); for (unsigned int i = 0; i < 3; ++i) for (unsigned int j = 0; j < 3; ++j) result << matrix[i][j] << " "; result << "\n"; result << " " << "Offset: "; const AffineTransform3D::OutputVectorType& offset = transform->GetOffset(); for (unsigned int i = 0; i < 3; ++i) result << offset[i] << " "; result << "\n"; result << " " << "Center: "; const AffineTransform3D::InputPointType& center = transform->GetCenter(); for (unsigned int i = 0; i < 3; ++i) result << center[i] << " "; result << "\n"; result << " " << "Translation: "; const AffineTransform3D::OutputVectorType& translation = transform->GetTranslation(); for (unsigned int i = 0; i < 3; ++i) result << translation[i] << " "; result << "\n"; result << " " << "Scale: "; const double* scale = transform->GetScale(); for (unsigned int i = 0; i < 3; ++i) result << scale[i] << " "; result << "\n"; result << " " << "Origin: "; const Point3D& origin = geometry->GetOrigin(); for (unsigned int i = 0; i < 3; ++i) result << origin[i] << " "; result << "\n"; result << " " << "Spacing: "; const Vector3D& spacing = geometry->GetSpacing(); for (unsigned int i = 0; i < 3; ++i) result << spacing[i] << " "; result << "\n"; result << " " << "TimeBounds: "; const TimeBounds timeBounds = geometry->GetTimeBounds(); for (unsigned int i = 0; i < 2; ++i) result << timeBounds[i] << " "; result << "\n"; } } ResetUserLocale(); return result.str(); } std::string mitk::TestDICOMLoading::trim(const std::string& pString, const std::string& pWhitespace) { const size_t beginStr = pString.find_first_not_of(pWhitespace); if (beginStr == std::string::npos) { // no content return ""; } const size_t endStr = pString.find_last_not_of(pWhitespace); const size_t range = endStr - beginStr + 1; return pString.substr(beginStr, range); } std::string mitk::TestDICOMLoading::reduce(const std::string& pString, const std::string& pFill, const std::string& pWhitespace) { // trim first std::string result(trim(pString, pWhitespace)); // replace sub ranges size_t beginSpace = result.find_first_of(pWhitespace); while (beginSpace != std::string::npos) { const size_t endSpace = result.find_first_not_of(pWhitespace, beginSpace); const size_t range = endSpace - beginSpace; result.replace(beginSpace, range, pFill); const size_t newStart = beginSpace + pFill.length(); beginSpace = result.find_first_of(pWhitespace, newStart); } return result; } bool mitk::TestDICOMLoading::CompareSpacedValueFields( const std::string& reference, const std::string& test, double /*eps*/ ) { bool result(true); // tokenize string, compare each token, if possible by float comparison std::stringstream referenceStream(reduce(reference)); std::stringstream testStream(reduce(test)); std::string refToken; std::string testToken; while ( std::getline( referenceStream, refToken, ' ' ) && std::getline ( testStream, testToken, ' ' ) ) { float refNumber; float testNumber; if ( this->StringToNumber(refToken, refNumber) ) { MITK_DEBUG << "Reference Token '" << refToken << "'" << " value " << refNumber << ", test Token '" << refToken << "'" << " value " << refNumber; if ( this->StringToNumber(testToken, testNumber) ) { result &= ( fabs(refNumber - testNumber) < mitk::eps ); } else { MITK_ERROR << refNumber << " cannot be compared to '" << testToken << "'"; } } else { MITK_DEBUG << "Token '" << refToken << "'" << " handled as string"; result &= refToken == testToken; } } if ( std::getline( referenceStream, refToken, ' ' ) ) { MITK_ERROR << "Reference string still had values when test string was already parsed: ref '" << reference << "', test '" << test << "'"; result = false; } else if ( std::getline( testStream, testToken, ' ' ) ) { MITK_ERROR << "Test string still had values when reference string was already parsed: ref '" << reference << "', test '" << test << "'"; result = false; } return result; } bool mitk::TestDICOMLoading::CompareImageInformationDumps( const std::string& referenceDump, const std::string& testDump ) { KeyValueMap reference = ParseDump(referenceDump); KeyValueMap test = ParseDump(testDump); bool testResult(true); // verify all expected values for (KeyValueMap::const_iterator refIter = reference.begin(); refIter != reference.end(); ++refIter) { const std::string& refKey = refIter->first; const std::string& refValue = refIter->second; if ( test.find(refKey) != test.end() ) { const std::string& testValue = test[refKey]; bool thisTestResult = CompareSpacedValueFields( refValue, testValue ); testResult &= thisTestResult; MITK_DEBUG << refKey << ": '" << refValue << "' == '" << testValue << "' ? " << (thisTestResult?"YES":"NO"); } else { MITK_ERROR << "Reference dump contains a key'" << refKey << "' (value '" << refValue << "')." ; MITK_ERROR << "This key is expected to be generated for tests (but was not). Most probably you need to update your test data."; return false; } } // now check test dump does not contain any additional keys for (KeyValueMap::const_iterator testIter = test.begin(); testIter != test.end(); ++testIter) { const std::string& key = testIter->first; const std::string& value = testIter->second; if ( reference.find(key) == reference.end() ) { MITK_ERROR << "Test dump contains an unexpected key'" << key << "' (value '" << value << "')." ; MITK_ERROR << "This key is not expected. Most probably you need to update your test data."; return false; } } return testResult; } mitk::TestDICOMLoading::KeyValueMap mitk::TestDICOMLoading::ParseDump( const std::string& dump ) { KeyValueMap parsedResult; std::string shredder(dump); std::stack surroundingKeys; std::stack expectedIndents; expectedIndents.push(0); while (true) { std::string::size_type newLinePos = shredder.find( '\n' ); if (newLinePos == std::string::npos || newLinePos == 0) break; std::string line = shredder.substr( 0, newLinePos ); shredder = shredder.erase( 0, newLinePos+1 ); std::string::size_type keyPosition = line.find_first_not_of( ' ' ); std::string::size_type colonPosition = line.find( ':' ); std::string key = line.substr(keyPosition, colonPosition - keyPosition); std::string::size_type firstSpacePosition = key.find_first_of(" "); if (firstSpacePosition != std::string::npos) { key.erase(firstSpacePosition); } if ( keyPosition > expectedIndents.top() ) { // more indent than before expectedIndents.push(keyPosition); } else if (keyPosition == expectedIndents.top() ) { if (!surroundingKeys.empty()) { surroundingKeys.pop(); // last of same length } } else { // less indent than before do expectedIndents.pop(); while (expectedIndents.top() != keyPosition); // unwind until current indent is found } if (!surroundingKeys.empty()) { key = surroundingKeys.top() + "." + key; // construct current key name } surroundingKeys.push(key); // this is the new embracing key std::string value = line.substr(colonPosition+1); MITK_DEBUG << " Key: '" << key << "' value '" << value << "'" ; parsedResult[key] = value; // store parsing result } return parsedResult; } diff --git a/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.h b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.h index ad546f5812..d7d266d196 100644 --- a/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.h +++ b/Core/Code/Testing/DICOMTesting/mitkTestDICOMLoading.h @@ -1,90 +1,105 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkTestDICOMLoading_h #define mitkTestDICOMLoading_h #include "mitkDicomSeriesReader.h" #include "mitkDICOMTestingExports.h" namespace mitk { class mitkDICOMTesting_EXPORT TestDICOMLoading { public: typedef DicomSeriesReader::StringContainer StringContainer; typedef std::list NodeList; typedef std::list ImageList; TestDICOMLoading(); ImageList LoadFiles( const StringContainer& files ); /** \brief Dump relevant image information for later comparison. \sa CompareImageInformationDumps */ std::string DumpImageInformation( const Image* image ); /** \brief Compare two image information dumps. \return true, if dumps are sufficiently equal (see parameters) \sa DumpImageInformation */ bool CompareImageInformationDumps( const std::string& reference, const std::string& test ); private: typedef std::map KeyValueMap; void SetDefaultLocale(); void ResetUserLocale(); std::string TypeIDToString( const std::type_info& ); KeyValueMap ParseDump( const std::string& dump ); bool CompareSpacedValueFields( const std::string& reference, const std::string& test, double eps = mitk::eps ); /** Compress whitespace in string \param pString input string \param pFill replacement whitespace (only whitespace in string after reduction) \param pWhitespace characters handled as whitespace */ std::string reduce(const std::string& pString, const std::string& pFill = " ", const std::string& pWhitespace = " \t"); /** Remove leading and trailing whitespace \param pString input string \param pWhitespace characters handled as whitespace */ std::string trim(const std::string& pString, const std::string& pWhitespace = " \t"); template bool StringToNumber(const std::string& s, T& value) { std::stringstream stream(s); stream >> value; return !stream.fail(); } const char* m_PreviousCLocale; std::locale m_PreviousCppLocale; }; } #endif diff --git a/Core/Code/Testing/files.cmake b/Core/Code/Testing/files.cmake index 3b704df89b..8f24b6f0bc 100644 --- a/Core/Code/Testing/files.cmake +++ b/Core/Code/Testing/files.cmake @@ -1,109 +1,113 @@ # tests with no extra command line parameter set(MODULE_TESTS mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageDataItemTest.cpp #mitkImageMapper2DTest.cpp mitkImageGeneratorTest.cpp mitkBaseDataTest.cpp #mitkImageToItkTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp mitkITKThreadingTest.cpp # mitkLevelWindowManagerTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp #mitkPipelineSmartPointerCorrectnessTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp #mitkRegistrationBaseTest.cpp #mitkSegmentationInterpolationTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeSlicedGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp #mitkAbstractTransformGeometryTest.cpp mitkStepperTest.cpp itkTotalVariationDenoisingImageFilterTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp #QmitkRenderingTestHelper.cpp mitkExceptionTest.cpp + mitkExtractSliceFilterTest.cpp ) # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkPlanePositionManagerTest.cpp mitkSurfaceVtkWriterTest.cpp #mitkImageSliceSelectorTest.cpp mitkImageTimeSelectorTest.cpp # mitkVtkPropRendererTest.cpp mitkDataNodeFactoryTest.cpp #mitkSTLFileReaderTest.cpp ) # list of images for which the tests are run set(MODULE_TESTIMAGES # Pic-Factory no more available in Core, test images now in .nrrd format US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS #mitkLabeledImageToSurfaceFilterTest.cpp #mitkExternalToolsTest.cpp mitkDataStorageTest.cpp mitkDataNodeTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkEventMapperTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp + mitkImageVtkMapper2DLevelWindowTest.cpp + mitkImageVtkMapper2DOpacityTest.cpp + mitkImageVtkMapper2DColorTest.cpp ) # Create an artificial module initializing class for # the usServiceListenerTest.cpp usFunctionGenerateModuleInit(testdriver_init_file NAME ${MODULE_NAME}TestDriver DEPENDS "Mitk" VERSION "0.1.0" EXECUTABLE ) -set(TEST_CPP_FILES ${testdriver_init_file} mitkRenderingTestHelper.cpp) \ No newline at end of file +set(TEST_CPP_FILES ${testdriver_init_file} mitkRenderingTestHelper.cpp) diff --git a/Core/Code/Testing/mitkExtractSliceFilterTest.cpp b/Core/Code/Testing/mitkExtractSliceFilterTest.cpp new file mode 100644 index 0000000000..0d6067d787 --- /dev/null +++ b/Core/Code/Testing/mitkExtractSliceFilterTest.cpp @@ -0,0 +1,1161 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: 7837 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//use this to create the test volume on the fly +#define CREATE_VOLUME + +//use this to save the created volume +//#define SAVE_VOLUME + +//use this to calculate the error from the sphere mathematical model to our pixel based one +//#define CALC_TESTFAILURE_DEVIATION + +//use this to render an oblique slice through a specified image +//#define SHOW_SLICE_IN_RENDER_WINDOW + +//use this to have infos printed in mbilog +//#define EXTRACTOR_DEBUG + + +/*these are the deviations calculated by the function CalcTestFailureDeviation (see for details)*/ +#define Testfailure_Deviation_Mean_128 0.853842 + +#define Testfailure_Deviation_Volume_128 0.145184 +#define Testfailure_Deviation_Diameter_128 1.5625 + + + +#define Testfailure_Deviation_Mean_256 0.397693 + +#define Testfailure_Deviation_Volume_256 0.0141357 +#define Testfailure_Deviation_Diameter_256 0.78125 + + + +#define Testfailure_Deviation_Mean_512 0.205277 + +#define Testfailure_Deviation_Volume_512 0.01993 +#define Testfailure_Deviation_Diameter_512 0.390625 + + + +class mitkExtractSliceFilterTestClass{ + +public: + + + static void TestSlice(mitk::PlaneGeometry* planeGeometry, std::string testname) + { + TestPlane = planeGeometry; + TestName = testname; + + float centerCoordValue = TestvolumeSize / 2.0; + float center[3] = {centerCoordValue, centerCoordValue, centerCoordValue}; + mitk::Point3D centerIndex(center); + + double radius = TestvolumeSize / 4.0; + if(TestPlane->Distance(centerIndex) >= radius ) return;//outside sphere + + + + //feed ExtractSliceFilter + mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New(); + + slicer->SetInput(TestVolume); + slicer->SetWorldGeometry(TestPlane); + slicer->Update(); + + MITK_TEST_CONDITION_REQUIRED(slicer->GetOutput() != NULL, "Extractor returned a slice"); + + mitk::Image::Pointer reslicedImage = slicer->GetOutput(); + + AccessFixedDimensionByItk(reslicedImage, TestSphereRadiusByItk, 2); + AccessFixedDimensionByItk(reslicedImage, TestSphereAreaByItk, 2); + + double devArea, devDiameter; + if(TestvolumeSize == 128.0){ devArea = Testfailure_Deviation_Volume_128; devDiameter = Testfailure_Deviation_Diameter_128; } + else if(TestvolumeSize == 256.0){devArea = Testfailure_Deviation_Volume_256; devDiameter = Testfailure_Deviation_Diameter_256;} + else if (TestvolumeSize == 512.0){devArea = Testfailure_Deviation_Volume_512; devDiameter = Testfailure_Deviation_Diameter_512;} + else{devArea = Testfailure_Deviation_Volume_128; devDiameter = Testfailure_Deviation_Diameter_128;} + + + std::string areatestName = TestName.append(" area"); + std::string diametertestName = TestName.append(" testing diameter"); + + //TODO think about the deviation, 1% makes no sense at all + MITK_TEST_CONDITION(std::abs(100 - testResults.percentageAreaCalcToPixel) < 1, areatestName ); + MITK_TEST_CONDITION(std::abs(100 - testResults.percentageRadiusToPixel) < 1, diametertestName ); + + #ifdef EXTRACTOR_DEBUG + MITK_INFO << TestName << " >>> " << "planeDistanceToSphereCenter: " << testResults.planeDistanceToSphereCenter; + MITK_INFO << "area in pixels: " << testResults.areaInPixel << " <-> area in mm: " << testResults.areaCalculated << " = " << testResults.percentageAreaCalcToPixel << "%"; + + MITK_INFO << "calculated diameter: " << testResults.diameterCalculated << " <-> diameter in mm: " << testResults.diameterInMM << " <-> diameter in pixel: " << testResults.diameterInPixel << " = " << testResults.percentageRadiusToPixel << "%"; + #endif + } + + + /* + * get the radius of the slice of a sphere based on pixel distance from edge to edge of the circle. + */ + template + static void TestSphereRadiusByItk (itk::Image* inputImage) + { + typedef itk::Image InputImageType; + + + //set the index to the middle of the image's edge at x and y axis + typename InputImageType::IndexType currentIndexX; + currentIndexX[0] = (int)(TestvolumeSize / 2.0); + currentIndexX[1] = 0; + + typename InputImageType::IndexType currentIndexY; + currentIndexY[0] = 0; + currentIndexY[1] = (int)(TestvolumeSize / 2.0); + + + //remember the last pixel value + double lastValueX = inputImage->GetPixel(currentIndexX); + double lastValueY = inputImage->GetPixel(currentIndexY); + + + //storage for the index marks + std::vector indicesX; + std::vector indicesY; + + + /*Get four indices on the edge of the circle*/ + while(currentIndexX[1] < TestvolumeSize && currentIndexX[0] < TestvolumeSize) + { + //move x direction + currentIndexX[1] += 1; + + //move y direction + currentIndexY[0] += 1; + + if(inputImage->GetPixel(currentIndexX) > lastValueX) + { + //mark the current index + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndexX[0]; + markIndex[1] = currentIndexX[1]; + + + indicesX.push_back(markIndex); + } + else if( inputImage->GetPixel(currentIndexX) < lastValueX) + { + //mark the current index + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndexX[0]; + markIndex[1] = currentIndexX[1] - 1;//value inside the sphere + + + indicesX.push_back(markIndex); + } + + if(inputImage->GetPixel(currentIndexY) > lastValueY) + { + //mark the current index + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndexY[0]; + markIndex[1] = currentIndexY[1]; + + + indicesY.push_back(markIndex); + } + else if( inputImage->GetPixel(currentIndexY) < lastValueY) + { + //mark the current index + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndexY[0]; + markIndex[1] = currentIndexY[1] - 1;//value inside the sphere + + + indicesY.push_back(markIndex); + } + + + //found both marks? + if(indicesX.size() == 2 && indicesY.size() == 2) break; + + //the new 'last' values + lastValueX = inputImage->GetPixel(currentIndexX); + lastValueY = inputImage->GetPixel(currentIndexY); + } + + /* + *If we are here we found the four marks on the edge of the circle. + *For the case our plane is rotated and shifted, we have to calculate the center of the circle, + *else the center is the intersection of both straight lines between the marks. + *When we have the center, the diameter of the circle will be checked to the reference value(math!). + */ + + //each distance from the first mark of each direction to the center of the straight line between the marks + double distanceToCenterX = std::abs(indicesX[0][1] - indicesX[1][1]) / 2.0; + double distanceToCenterY = std::abs(indicesY[0][0] - indicesY[1][0]) / 2.0; + + + //the center of the straight lines + typename InputImageType::IndexType centerX, centerY; + + centerX[0] = indicesX[0][0]; + centerX[1] = indicesX[0][1] + distanceToCenterX; + //TODO think about implicit cast to int. this is not the real center of the image, which could be between two pixels + + //centerY[0] = indicesY[0][0] + distanceToCenterY; + //centerY[1] = inidcesY[0][1]; + + typename InputImageType::IndexType currentIndex(centerX); + lastValueX = inputImage->GetPixel(currentIndex); + + long sumpixels = 0; + + std::vector diameterIndices; + + //move up + while(currentIndex[1] < TestvolumeSize) + { + currentIndex[1] += 1; + + if( inputImage->GetPixel(currentIndex) != lastValueX) + { + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndex[0]; + markIndex[1] = currentIndex[1] - 1; + + diameterIndices.push_back(markIndex); + break; + } + + sumpixels++; + lastValueX = inputImage->GetPixel(currentIndex); + } + + currentIndex[1] -= sumpixels; //move back to center to go in the other direction + lastValueX = inputImage->GetPixel(currentIndex); + + //move down + while(currentIndex[1] >= 0) + { + currentIndex[1] -= 1; + + if( inputImage->GetPixel(currentIndex) != lastValueX) + { + typename InputImageType::IndexType markIndex; + markIndex[0] = currentIndex[0]; + markIndex[1] = currentIndex[1];//outside sphere because we want to calculate the distance from edge to edge + + diameterIndices.push_back(markIndex); + break; + } + + sumpixels++; + lastValueX = inputImage->GetPixel(currentIndex); + } + + + + /* + *Now sumpixels should be the apromximate diameter of the circle. This is checked with the calculated diameter from the plane transformation(math). + */ + mitk::Point3D volumeCenter; + volumeCenter[0] = volumeCenter[1] = volumeCenter[2] = TestvolumeSize / 2.0; + + + double planeDistanceToSphereCenter = TestPlane->Distance(volumeCenter); + + + double sphereRadius = TestvolumeSize/4.0; + + //calculate the radius of the circle cut from the sphere by the plane + double diameter = 2.0 * std::sqrt(std::pow(sphereRadius, 2) - std::pow( planeDistanceToSphereCenter , 2)); + + double percentageRadiusToPixel = 100 / diameter * sumpixels; + + + + /* + *calculate the radius in mm by the both marks of the center line by using the world coordinates + */ + //get the points as 3D coordinates + mitk::Vector3D diameterPointRight, diameterPointLeft; + + diameterPointRight[2] = diameterPointLeft[2] = 0.0; + + diameterPointLeft[0] = diameterIndices[0][0]; + diameterPointLeft[1] = diameterIndices[0][1]; + + diameterPointRight[0] = diameterIndices[1][0]; + diameterPointRight[1] = diameterIndices[1][1]; + + //transform to worldcoordinates + TestVolume->GetGeometry()->IndexToWorld(diameterPointLeft, diameterPointLeft); + TestVolume->GetGeometry()->IndexToWorld(diameterPointRight, diameterPointRight); + + //euklidian distance + double diameterInMM = ( (diameterPointLeft * -1.0) + diameterPointRight).GetNorm(); + + + testResults.diameterInMM = diameterInMM; + testResults.diameterCalculated = diameter; + testResults.diameterInPixel = sumpixels; + testResults.percentageRadiusToPixel = percentageRadiusToPixel; + testResults.planeDistanceToSphereCenter = planeDistanceToSphereCenter; + } + + + + + + /*brute force the area pixel by pixel*/ + template + static void TestSphereAreaByItk (itk::Image* inputImage) + { + typedef itk::Image InputImageType; + typedef itk::ImageRegionConstIterator< InputImageType > ImageIterator; + + + ImageIterator imageIterator( inputImage, inputImage->GetLargestPossibleRegion() ); + imageIterator.GoToBegin(); + + int sumPixelsInArea = 0; + + while( !imageIterator.IsAtEnd() ) + { + if(inputImage->GetPixel(imageIterator.GetIndex()) == pixelValueSet) sumPixelsInArea++; + ++imageIterator; + } + + mitk::Point3D volumeCenter; + volumeCenter[0] = volumeCenter[1] = volumeCenter[2] = TestvolumeSize / 2.0; + + + double planeDistanceToSphereCenter = TestPlane->Distance(volumeCenter); + + double sphereRadius = TestvolumeSize/4.0; + + //calculate the radius of the circle cut from the sphere by the plane + double radius = std::sqrt(std::pow(sphereRadius, 2) - std::pow( planeDistanceToSphereCenter , 2)); + + double areaInMM = 3.14159265358979 * std::pow(radius, 2); + + + testResults.areaCalculated = areaInMM; + testResults.areaInPixel = sumPixelsInArea; + testResults.percentageAreaCalcToPixel = 100 / areaInMM * sumPixelsInArea; + } + + + + /* + * random a voxel. define plane through this voxel. reslice at the plane. compare the pixel vaues of the voxel + * in the volume with the pixel value in the resliced image. + * there are some indice shifting problems which causes the test to fail for oblique planes. seems like the chosen + * worldcoordinate is not corrresponding to the index in the 2D image. and so the pixel values are not the same as + * expected. + */ + static void PixelvalueBasedTest() + { + /* setup itk image */ + typedef itk::Image ImageType; + + typedef itk::ImageRegionConstIterator< ImageType > ImageIterator; + + ImageType::Pointer image = ImageType::New(); + + ImageType::IndexType start; + start[0] = start[1] = start[2] = 0; + + ImageType::SizeType size; + size[0] = size[1] = size[2] = 32; + + ImageType::RegionType imgRegion; + imgRegion.SetSize(size); + imgRegion.SetIndex(start); + + image->SetRegions(imgRegion); + image->SetSpacing(1.0); + image->Allocate(); + + + ImageIterator imageIterator( image, image->GetLargestPossibleRegion() ); + imageIterator.GoToBegin(); + + + unsigned short pixelValue = 0; + + //fill the image with distinct values + while ( !imageIterator.IsAtEnd() ) + { + image->SetPixel(imageIterator.GetIndex(), pixelValue); + ++imageIterator; + ++pixelValue; + } + /* end setup itk image */ + + + + mitk::Image::Pointer imageInMitk; + CastToMitkImage(image, imageInMitk); + + + + /*mitk::ImageWriter::Pointer writer = mitk::ImageWriter::New(); + writer->SetInput(imageInMitk); + std::string file = "C:\\Users\\schroedt\\Desktop\\cube.nrrd"; + writer->SetFileName(file); + writer->Update();*/ + + PixelvalueBasedTestByPlane(imageInMitk, mitk::PlaneGeometry::Frontal); + PixelvalueBasedTestByPlane(imageInMitk, mitk::PlaneGeometry::Sagittal); + PixelvalueBasedTestByPlane(imageInMitk, mitk::PlaneGeometry::Transversal); + + } + + static void PixelvalueBasedTestByPlane(mitk::Image* imageInMitk, mitk::PlaneGeometry::PlaneOrientation orientation){ + + typedef itk::Image ImageType; + + //set the seed of the rand function + srand((unsigned)time(0)); + + /* setup a random orthogonal plane */ + int sliceindex = 17;//rand() % 32; + bool isFrontside = true; + bool isRotated = false; + + + if( orientation == mitk::PlaneGeometry::Transversal) + { + /*isFrontside = false; + isRotated = true;*/ + } + + + + mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); + + + plane->InitializeStandardPlane(imageInMitk->GetGeometry(), orientation, sliceindex, isFrontside, isRotated); + + mitk::Point3D origin = plane->GetOrigin(); + mitk::Vector3D normal; + normal = plane->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + plane->SetOrigin(origin); + + //we dont need this any more, because we are only testing orthogonal planes + /*mitk::Vector3D rotationVector; + rotationVector[0] = randFloat(); + rotationVector[1] = randFloat(); + rotationVector[2] = randFloat(); + + + float degree = randFloat() * 180.0; + + mitk::RotationOperation* op = new mitk::RotationOperation(mitk::OpROTATE, plane->GetCenter(), rotationVector, degree); + plane->ExecuteOperation(op); + delete op;*/ + + /* end setup plane */ + + + /* define a point in the 3D volume. + * add the two axis vectors of the plane (each multiplied with a + * random number) to the origin. now the two random numbers + * become our index coordinates in the 2D image, because the + * length of the axis vectors is 1. + */ + mitk::Point3D planeOrigin = plane->GetOrigin(); + mitk::Vector3D axis0, axis1; + axis0 = plane->GetAxisVector(0); + axis1 = plane->GetAxisVector(1); + axis0.Normalize(); + axis1.Normalize(); + + + unsigned char n1 = 7;// rand() % 32; + unsigned char n2 = 13;// rand() % 32; + + + mitk::Point3D testPoint3DInWorld; + testPoint3DInWorld = planeOrigin + (axis0 * n1) + (axis1 * n2); + + //get the index of the point in the 3D volume + ImageType::IndexType testPoint3DInIndex; + imageInMitk->GetGeometry()->WorldToIndex(testPoint3DInWorld, testPoint3DInIndex); + + mitk::Index3D testPoint2DInIndex; + + /* end define a point in the 3D volume.*/ + + + //do reslicing at the plane + mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New(); + slicer->SetInput(imageInMitk); + slicer->SetWorldGeometry(plane); + + slicer->Update(); + + mitk::Image::Pointer slice = slicer->GetOutput(); + + // Get TestPoiont3D as Index in Slice + slice->GetGeometry()->WorldToIndex(testPoint3DInWorld,testPoint2DInIndex); + + + mitk::Point3D p, sliceIndexToWorld, imageIndexToWorld; + p[0] = testPoint2DInIndex[0]; + p[1] = testPoint2DInIndex[1]; + p[2] = testPoint2DInIndex[2]; + slice->GetGeometry()->IndexToWorld(p, sliceIndexToWorld); + + p[0] = testPoint3DInIndex[0]; + p[1] = testPoint3DInIndex[1]; + p[2] = testPoint3DInIndex[2]; + imageInMitk->GetGeometry()->IndexToWorld(p, imageIndexToWorld); + + + + //compare the pixelvalues of the defined point in the 3D volume with the value of the resliced image + unsigned short valueAt3DVolume = imageInMitk->GetPixelValueByIndex(testPoint3DInIndex);//image->GetPixel(testPoint3DInIndex); + unsigned short valueAt3DVolumeByWorld = imageInMitk->GetPixelValueByWorldCoordinate(testPoint3DInWorld); + unsigned short valueAtSlice = slice->GetPixelValueByIndex(testPoint2DInIndex); + + //valueAt3DVolume == valueAtSlice is not always working. because of rounding errors + //indices are shifted + MITK_TEST_CONDITION(valueAt3DVolume == valueAtSlice, "comparing pixelvalues for orthogonal plane"); + + + vtkSmartPointer imageInVtk = vtkSmartPointer::New(); + imageInVtk = imageInMitk->GetVtkImageData(); + vtkSmartPointer sliceInVtk = vtkSmartPointer::New(); + sliceInVtk = slice->GetVtkImageData(); + + double PixelvalueByMitkOutput = sliceInVtk->GetScalarComponentAsDouble(n1, n2, 0, 0); + double valueVTKinImage = imageInVtk->GetScalarComponentAsDouble(testPoint3DInIndex[0], testPoint3DInIndex[1], testPoint3DInIndex[2], 0); + + + /* Test that everything is working equally if vtkoutput is used instead of the default output + * from mitk ImageToImageFilter + */ + mitk::ExtractSliceFilter::Pointer slicerWithVtkOutput = mitk::ExtractSliceFilter::New(); + slicerWithVtkOutput->SetInput(imageInMitk); + slicerWithVtkOutput->SetWorldGeometry(plane); + slicerWithVtkOutput->SetVtkOutputRequest(true); + + slicerWithVtkOutput->Update(); + vtkSmartPointer vtkImageByVtkOutput = vtkSmartPointer::New(); + vtkImageByVtkOutput = slicerWithVtkOutput->GetVtkOutput(); + double PixelvalueByVtkOutput = vtkImageByVtkOutput->GetScalarComponentAsDouble(n1, n2, 0, 0); + + MITK_TEST_CONDITION(PixelvalueByMitkOutput == PixelvalueByVtkOutput, "testing convertion of image output vtk->mitk by reslicer"); + + + +/*================ mbilog outputs ===========================*/ +#ifdef EXTRACTOR_DEBUG + MITK_INFO << "\n" << "TESTINFO index: " << sliceindex << " orientation: " << orientation << " frontside: " << isFrontside << " rotated: " << isRotated; + MITK_INFO << "\n" << "slice index to world: " << sliceIndexToWorld; + MITK_INFO << "\n" << "image index to world: " << imageIndexToWorld; + + MITK_INFO << "\n" << "vtk: slice: " << PixelvalueByMitkOutput << ", image: "<< valueVTKinImage; + + MITK_INFO << "\n" << "testPoint3D InWorld" << testPoint3DInWorld << " is " << testPoint2DInIndex << " in 2D"; + MITK_INFO << "\n" << "randoms: " << ((int)n1) << ", " << ((int)n2); + MITK_INFO << "\n" << "point is inside plane: " << plane->IsInside(testPoint3DInWorld) << " and volume: " << imageInMitk->GetGeometry()->IsInside(testPoint3DInWorld); + + MITK_INFO << "\n" << "volume idx: " << testPoint3DInIndex << " = " << valueAt3DVolume ; + MITK_INFO << "\n" << "volume world: " << testPoint3DInWorld << " = " << valueAt3DVolumeByWorld ; + MITK_INFO << "\n" << "slice idx: " << testPoint2DInIndex << " = " << valueAtSlice ; + + mitk::Index3D curr; + curr[0] = curr[1] = curr[2] = 0; + + for( int i = 0; i < 32 ; ++i){ + for( int j = 0; j < 32; ++j){ + ++curr[1]; + if(slice->GetPixelValueByIndex(curr) == valueAt3DVolume){ + MITK_INFO << "\n" << valueAt3DVolume << " MATCHED mitk " << curr; + } + } + curr[1] = 0; + ++curr[0]; + } + + typedef itk::Image Image2DType; + + Image2DType::Pointer img = Image2DType::New(); + CastToItkImage(slice, img); + typedef itk::ImageRegionConstIterator< Image2DType > Iterator2D; + + Iterator2D iter(img, img->GetLargestPossibleRegion()); + iter.GoToBegin(); + while( !iter.IsAtEnd() ){ + + if(img->GetPixel(iter.GetIndex()) == valueAt3DVolume) MITK_INFO << "\n" << valueAt3DVolume << " MATCHED itk " << iter.GetIndex(); + + ++iter; + } +#endif //EXTRACTOR_DEBUG + } + + + /* random a float value */ + static float randFloat(){ return (((float)rand()+1.0) / ((float)RAND_MAX + 1.0)) + (((float)rand()+1.0) / ((float)RAND_MAX + 1.0)) / ((float)RAND_MAX + 1.0);} + + + + + /* create a sphere with the size of the given testVolumeSize*/ + static void InitializeTestVolume() + { + + #ifdef CREATE_VOLUME + + + //do sphere creation + ItkVolumeGeneration(); + + #ifdef SAVE_VOLUME + //save in file + mitk::ImageWriter::Pointer writer = mitk::ImageWriter::New(); + writer->SetInput(TestVolume); + + + std::string file; + + std::ostringstream filename; + filename << "C:\\home\\schroedt\\MITK\\Modules\\ImageExtraction\\Testing\\Data\\sphere_"; + filename << TestvolumeSize; + filename << ".nrrd"; + + file = filename.str(); + + writer->SetFileName(file); + writer->Update(); + #endif//SAVE_VOLUME + + #endif + + + #ifndef CREATE_VOLUME //read from file + + mitk::StandardFileLocations::Pointer locator = mitk::StandardFileLocations::GetInstance(); + + std::string filename = locator->FindFile("sphere_512.nrrd.mhd", "Modules/ImageExtraction/Testing/Data"); + + mitk::ItkImageFileReader::Pointer reader = mitk::ItkImageFileReader::New(); + reader->SetFileName(filename); + + reader->Update(); + TestVolume = reader->GetOutput(); + + #endif + + #ifdef CALC_TESTFAILURE_DEVIATION + //get the TestFailureDeviation in % + AccessFixedDimensionByItk(TestVolume, CalcTestFailureDeviation, 3); + #endif + } + + + //the test result of the sphere reslice + struct SliceProperties{ + double planeDistanceToSphereCenter; + double diameterInMM; + double diameterInPixel; + double diameterCalculated; + double percentageRadiusToPixel; + double areaCalculated; + double areaInPixel; + double percentageAreaCalcToPixel; + }; + + + static mitk::Image::Pointer TestVolume; + static double TestvolumeSize; + static mitk::PlaneGeometry::Pointer TestPlane; + static std::string TestName; + static unsigned char pixelValueSet; + static SliceProperties testResults; + static double TestFailureDeviation; + + + +private: + + /* + * Generate a sphere with a radius of TestvolumeSize / 4.0 + */ + static void ItkVolumeGeneration () + { + typedef itk::Image TestVolumeType; + + typedef itk::ImageRegionConstIterator< TestVolumeType > ImageIterator; + + TestVolumeType::Pointer sphereImage = TestVolumeType::New(); + + TestVolumeType::IndexType start; + start[0] = start[1] = start[2] = 0; + + TestVolumeType::SizeType size; + size[0] = size[1] = size[2] = TestvolumeSize; + + TestVolumeType::RegionType imgRegion; + imgRegion.SetSize(size); + imgRegion.SetIndex(start); + + sphereImage->SetRegions(imgRegion); + sphereImage->SetSpacing(1.0); + sphereImage->Allocate(); + + sphereImage->FillBuffer(0); + + + mitk::Vector3D center; + center[0] = center[1] = center[2] = TestvolumeSize / 2.0; + + + double radius = TestvolumeSize / 4.0; + + double pixelValue = pixelValueSet; + + double distanceToCenter = 0.0; + + + ImageIterator imageIterator( sphereImage, sphereImage->GetLargestPossibleRegion() ); + imageIterator.GoToBegin(); + + + mitk::Vector3D currentVoxelInIndex; + + while ( !imageIterator.IsAtEnd() ) + { + currentVoxelInIndex[0] = imageIterator.GetIndex()[0]; + currentVoxelInIndex[1] = imageIterator.GetIndex()[1]; + currentVoxelInIndex[2] = imageIterator.GetIndex()[2]; + + distanceToCenter = (center + ( currentVoxelInIndex * -1.0 )).GetNorm(); + + //if distance to center is smaller then the radius of the sphere + if( distanceToCenter < radius) + { + sphereImage->SetPixel(imageIterator.GetIndex(), pixelValue); + } + + ++imageIterator; + } + + CastToMitkImage(sphereImage, TestVolume); + } + + + + + + /* calculate the devation of the voxel object to the mathematical sphere object. + * this is use to make a statement about the accuracy of the resliced image, eg. the circle's diameter or area. + */ + template + static void CalcTestFailureDeviation (itk::Image* inputImage) + { + typedef itk::Image InputImageType; + typedef itk::ImageRegionConstIterator< InputImageType > ImageIterator; + + ImageIterator iterator(inputImage, inputImage->GetLargestPossibleRegion()); + iterator.GoToBegin(); + + int volumeInPixel = 0; + + while( !iterator.IsAtEnd() ) + { + if(inputImage->GetPixel(iterator.GetIndex()) == pixelValueSet) volumeInPixel++; + ++iterator; + } + + double diameter = TestvolumeSize / 2.0; + double volumeCalculated = (1.0 / 6.0) * 3.14159265358979 * std::pow(diameter, 3); + + + double volumeDeviation = std::abs( 100 - (100 / volumeCalculated * volumeInPixel) ); + + + typename InputImageType::IndexType index; + index[0] = index[1] = TestvolumeSize / 2.0; + index[2] = 0; + + int sumpixels = 0; + while (index[2] < TestvolumeSize ) + { + if(inputImage->GetPixel(index) == pixelValueSet) sumpixels++; + index[2] += 1; + } + + + double diameterDeviation = std::abs( 100 - (100 / diameter * sumpixels) ); + #ifdef DEBUG + MITK_INFO << "volume deviation: " << volumeDeviation << " diameter deviation:" << diameterDeviation; + #endif + mitkExtractSliceFilterTestClass::TestFailureDeviation = (volumeDeviation + diameterDeviation) / 2.0; + } + + +}; +/*================ #END class ================*/ + + + + + +/*================#BEGIN Instanciation of members ================*/ +mitk::Image::Pointer mitkExtractSliceFilterTestClass::TestVolume = mitk::Image::New(); +double mitkExtractSliceFilterTestClass::TestvolumeSize = 256.0; +mitk::PlaneGeometry::Pointer mitkExtractSliceFilterTestClass::TestPlane = mitk::PlaneGeometry::New(); +std::string mitkExtractSliceFilterTestClass::TestName = ""; +unsigned char mitkExtractSliceFilterTestClass::pixelValueSet = 255; +mitkExtractSliceFilterTestClass::SliceProperties mitkExtractSliceFilterTestClass::testResults = {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}; +double mitkExtractSliceFilterTestClass::TestFailureDeviation = 0.0; +/*================ #END Instanciation of members ================*/ + + + + + +/*================ #BEGIN test main ================*/ +int mitkExtractSliceFilterTest(int argc, char* argv[]) +{ + + MITK_TEST_BEGIN("mitkExtractSliceFilterTest") + + + //pixelvalue based testing + mitkExtractSliceFilterTestClass::PixelvalueBasedTest(); + + //initialize sphere test volume + mitkExtractSliceFilterTestClass::InitializeTestVolume(); + + + mitk::Vector3D spacing = mitkExtractSliceFilterTestClass::TestVolume->GetGeometry()->GetSpacing(); + + + //the center of the sphere = center of image + double sphereCenter = mitkExtractSliceFilterTestClass::TestvolumeSize / 2.0; + + double planeSize = mitkExtractSliceFilterTestClass::TestvolumeSize; + + + + /* transversal plane */ + mitk::PlaneGeometry::Pointer geometryTransversal = mitk::PlaneGeometry::New(); + geometryTransversal->InitializeStandardPlane(planeSize, planeSize, spacing, mitk::PlaneGeometry::Transversal, sphereCenter, false, true); + geometryTransversal->ChangeImageGeometryConsideringOriginOffset(true); + + mitk::Point3D origin = geometryTransversal->GetOrigin(); + mitk::Vector3D normal; + normal = geometryTransversal->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + //geometryTransversal->SetOrigin(origin); + + mitkExtractSliceFilterTestClass::TestSlice(geometryTransversal, "Testing transversal plane"); + /* end transversal plane */ + + + + /* sagittal plane */ + mitk::PlaneGeometry::Pointer geometrySagital = mitk::PlaneGeometry::New(); + geometrySagital->InitializeStandardPlane(planeSize, planeSize, spacing, mitk::PlaneGeometry::Sagittal, sphereCenter, true, false); + geometrySagital->ChangeImageGeometryConsideringOriginOffset(true); + + origin = geometrySagital->GetOrigin(); + normal = geometrySagital->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + //geometrySagital->SetOrigin(origin); + + mitkExtractSliceFilterTestClass::TestSlice(geometrySagital, "Testing sagittal plane"); + /* sagittal plane */ + + + + /* sagittal shifted plane */ + mitk::PlaneGeometry::Pointer geometrySagitalShifted = mitk::PlaneGeometry::New(); + geometrySagitalShifted->InitializeStandardPlane(planeSize, planeSize, spacing, mitk::PlaneGeometry::Sagittal, (sphereCenter - 14), true, false); + geometrySagitalShifted->ChangeImageGeometryConsideringOriginOffset(true); + + origin = geometrySagitalShifted->GetOrigin(); + normal = geometrySagitalShifted->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + //geometrySagitalShifted->SetOrigin(origin); + + mitkExtractSliceFilterTestClass::TestSlice(geometrySagitalShifted, "Testing sagittal plane shifted"); + /* end sagittal shifted plane */ + + + + /* coronal plane */ + mitk::PlaneGeometry::Pointer geometryCoronal = mitk::PlaneGeometry::New(); + geometryCoronal->InitializeStandardPlane(planeSize, planeSize, spacing, mitk::PlaneGeometry::Frontal, sphereCenter, true, false); + geometryCoronal->ChangeImageGeometryConsideringOriginOffset(true); + + origin = geometryCoronal->GetOrigin(); + normal = geometryCoronal->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + //geometryCoronal->SetOrigin(origin); + + mitkExtractSliceFilterTestClass::TestSlice(geometryCoronal, "Testing coronal plane"); + /* end coronal plane */ + + + + /* oblique plane */ + mitk::PlaneGeometry::Pointer obliquePlane = mitk::PlaneGeometry::New(); + obliquePlane->InitializeStandardPlane(planeSize, planeSize, spacing, mitk::PlaneGeometry::Sagittal, sphereCenter, true, false); + obliquePlane->ChangeImageGeometryConsideringOriginOffset(true); + + origin = obliquePlane->GetOrigin(); + normal = obliquePlane->GetNormal(); + + + normal.Normalize(); + + origin += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + //obliquePlane->SetOrigin(origin); + + mitk::Vector3D rotationVector; + rotationVector[0] = 0.2; + rotationVector[1] = 0.4; + rotationVector[2] = 0.62; + + float degree = 37.0; + + mitk::RotationOperation* op = new mitk::RotationOperation(mitk::OpROTATE, obliquePlane->GetCenter(), rotationVector, degree); + obliquePlane->ExecuteOperation(op); + delete op; + + mitkExtractSliceFilterTestClass::TestSlice(obliquePlane, "Testing oblique plane"); + /* end oblique plane */ + + + + #ifdef SHOW_SLICE_IN_RENDER_WINDOW + /*================ #BEGIN vtk render code ================*/ + + //set reslicer for renderwindow + mitk::ItkImageFileReader::Pointer reader = mitk::ItkImageFileReader::New(); + + std::string filename = "C:\\home\\Pics\\Pic3D.nrrd"; + reader->SetFileName(filename); + + reader->Update(); + + mitk::Image::Pointer pic = reader->GetOutput(); + vtkSmartPointer slicer = vtkSmartPointer::New(); + + slicer->SetInput(pic->GetVtkImageData()); + + + mitk::PlaneGeometry::Pointer obliquePl = mitk::PlaneGeometry::New(); + obliquePl->InitializeStandardPlane(pic->GetGeometry(), mitk::PlaneGeometry::Sagittal, pic->GetGeometry()->GetCenter()[0], true, false); + obliquePl->ChangeImageGeometryConsideringOriginOffset(true); + + mitk::Point3D origin2 = obliquePl->GetOrigin(); + mitk::Vector3D n; + n = obliquePl->GetNormal(); + + + n.Normalize(); + + origin2 += n * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + + obliquePl->SetOrigin(origin2); + + mitk::Vector3D rotation; + rotation[0] = 0.534307; + rotation[1] = 0.000439605; + rotation[2] = 0.423017; + MITK_INFO << rotation; + + float rotateDegree = 70; + + mitk::RotationOperation* operation = new mitk::RotationOperation(mitk::OpROTATE, obliquePl->GetCenter(), rotationVector, degree); + obliquePl->ExecuteOperation(operation); + delete operation; + + + double origin[3]; + origin[0] = obliquePl->GetOrigin()[0]; + origin[1] = obliquePl->GetOrigin()[1]; + origin[2] = obliquePl->GetOrigin()[2]; + slicer->SetResliceAxesOrigin(origin); + + + mitk::Vector3D right, bottom, normal; + right = obliquePl->GetAxisVector( 0 ); + bottom = obliquePl->GetAxisVector( 1 ); + normal = obliquePl->GetNormal(); + + right.Normalize(); + bottom.Normalize(); + normal.Normalize(); + + double cosines[9]; + + mitk::vnl2vtk(right.GetVnlVector(), cosines);//x + + mitk::vnl2vtk(bottom.GetVnlVector(), cosines + 3);//y + + mitk::vnl2vtk(normal.GetVnlVector(), cosines + 6);//n + + slicer->SetResliceAxesDirectionCosines(cosines); + + slicer->SetOutputDimensionality(2); + slicer->Update(); + + + //set vtk renderwindow + vtkSmartPointer vtkPlane = vtkSmartPointer::New(); + vtkPlane->SetOrigin(0.0, 0.0, 0.0); + + //These two points define the axes of the plane in combination with the origin. + //Point 1 is the x-axis and point 2 the y-axis. + //Each plane is transformed according to the view (transversal, coronal and saggital) afterwards. + vtkPlane->SetPoint1(1.0, 0.0, 0.0); //P1: (xMax, yMin, depth) + vtkPlane->SetPoint2(0.0, 1.0, 0.0); //P2: (xMin, yMax, depth) + //these are not the correct values for all slices, only a square plane by now + + vtkSmartPointer imageMapper = vtkSmartPointer::New(); + imageMapper->SetInputConnection(vtkPlane->GetOutputPort()); + + + vtkSmartPointer lookupTable = vtkSmartPointer::New(); + + //built a default lookuptable + lookupTable->SetRampToLinear(); + lookupTable->SetSaturationRange( 0.0, 0.0 ); + lookupTable->SetHueRange( 0.0, 0.0 ); + lookupTable->SetValueRange( 0.0, 1.0 ); + lookupTable->Build(); + //map all black values to transparent + lookupTable->SetTableValue(0, 0.0, 0.0, 0.0, 0.0); + lookupTable->SetRange(-255.0, 255.0); + //lookupTable->SetRange(-1022.0, 1184.0);//pic3D range + + vtkSmartPointer texture = vtkSmartPointer::New(); + + + texture->SetInput(slicer->GetOutput()); + + texture->SetLookupTable(lookupTable); + + texture->SetMapColorScalarsThroughLookupTable(true); + + vtkSmartPointer imageActor = vtkSmartPointer::New(); + imageActor->SetMapper(imageMapper); + imageActor->SetTexture(texture); + + + // Setup renderers + vtkSmartPointer renderer = vtkSmartPointer::New(); + renderer->AddActor(imageActor); + + // Setup render window + vtkSmartPointer renderWindow = vtkSmartPointer::New(); + renderWindow->AddRenderer(renderer); + + // Setup render window interactor + vtkSmartPointer renderWindowInteractor = vtkSmartPointer::New(); + vtkSmartPointer style = vtkSmartPointer::New(); + renderWindowInteractor->SetInteractorStyle(style); + + // Render and start interaction + renderWindowInteractor->SetRenderWindow(renderWindow); + //renderer->AddViewProp(imageActor); + + + renderWindow->Render(); + renderWindowInteractor->Start(); + // always end with this! + /*================ #END vtk render code ================*/ + #endif //SHOW_SLICE_IN_RENDER_WINDOW + + + MITK_TEST_END() +} diff --git a/Core/Code/Testing/mitkImageVtkMapper2DColorTest.cpp b/Core/Code/Testing/mitkImageVtkMapper2DColorTest.cpp new file mode 100644 index 0000000000..0773680ad2 --- /dev/null +++ b/Core/Code/Testing/mitkImageVtkMapper2DColorTest.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +//MITK +#include "mitkTestingMacros.h" +#include "mitkRenderingTestHelper.h" + +//VTK +#include + + +int mitkImageVtkMapper2DColorTest(int argc, char* argv[]) +{ + // load all arguments into a datastorage, take last argument as reference rendering + // setup a renderwindow of fixed size X*Y + // render the datastorage + // compare rendering to reference image + MITK_TEST_BEGIN("mitkImageVtkMapper2DTest") + + // enough parameters? + if ( argc < 2 ) + { + MITK_TEST_OUTPUT( << "Usage: " << std::string(*argv) << " [file1 file2 ...] outputfile" ) + MITK_TEST_OUTPUT( << "Will render a central transversal slice of all given files into outputfile" ) + exit( EXIT_SUCCESS ); + } + + mitkRenderingTestHelper renderingHelper(640, 480, argc, argv); + //Set the opacity for all images + renderingHelper.SetProperty("use color", mitk::BoolProperty::New(true)); + renderingHelper.SetProperty("color", mitk::ColorProperty::New(0.0f, 0.0f, 255.0f)); + //for now this test renders in sagittal view direction + renderingHelper.SetViewDirection(mitk::SliceNavigationController::Sagittal); + renderingHelper.Render(); + + //use this to generate a reference screenshot or save the file: + bool generateReferenceScreenshot = false; + if(generateReferenceScreenshot) + { + renderingHelper.SaveAsPNG("/home/kilgus/Pictures/RenderingTestData/output.png"); + } + + //### Usage of vtkRegressionTestImage: + //vtkRegressionTestImage( vtkRenderWindow ) + //Set a vtkRenderWindow containing the desired scene. + //vtkRegressionTestImage automatically searches in argc and argv[] + //for a path a valid image with -V. If the test failed with the + //first image (foo.png) check if there are images of the form + //foo_N.png (where N=1,2,3...) and compare against them. + int retVal = vtkRegressionTestImage( renderingHelper.GetVtkRenderWindow() ); + + //retVal meanings: (see VTK/Rendering/vtkTesting.h) + //0 = test failed + //1 = test passed + //2 = test not run + //3 = something with vtkInteraction + MITK_TEST_CONDITION( retVal == 1, "VTK test result positive" ); + + MITK_TEST_END(); +} + diff --git a/Core/Code/Testing/mitkImageVtkMapper2DLevelWindowTest.cpp b/Core/Code/Testing/mitkImageVtkMapper2DLevelWindowTest.cpp new file mode 100644 index 0000000000..fd62b2a8f1 --- /dev/null +++ b/Core/Code/Testing/mitkImageVtkMapper2DLevelWindowTest.cpp @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +//MITK +#include "mitkTestingMacros.h" +#include "mitkRenderingTestHelper.h" +#include +#include + +//VTK +#include + +int mitkImageVtkMapper2DLevelWindowTest(int argc, char* argv[]) +{ + // load all arguments into a datastorage, take last argument as reference rendering + // setup a renderwindow of fixed size X*Y + // render the datastorage + // compare rendering to reference image + MITK_TEST_BEGIN("mitkImageVtkMapper2DTest") + + // enough parameters? + if ( argc < 2 ) + { + MITK_TEST_OUTPUT( << "Usage: " << std::string(*argv) << " [file1 file2 ...] outputfile" ) + MITK_TEST_OUTPUT( << "Will render a central transversal slice of all given files into outputfile" ) + exit( EXIT_SUCCESS ); + } + + mitkRenderingTestHelper renderingHelper(640, 480, argc, argv); + //chose a level window: here we randomly chosen the blood preset. + mitk::LevelWindowPreset* levelWindowPreset = mitk::LevelWindowPreset::New(); + bool loadedPreset = levelWindowPreset->LoadPreset(); + MITK_TEST_CONDITION_REQUIRED(loadedPreset == true, "Testing if level window preset could be loaded"); + double level = levelWindowPreset->getLevel("Blood"); + double window = levelWindowPreset->getWindow("Blood"); + //apply level window to all images + renderingHelper.SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(level, window)) ); + //for now this test renders Sagittal + renderingHelper.SetViewDirection(mitk::SliceNavigationController::Sagittal); + renderingHelper.Render(); + + //use this to generate a reference screenshot or save the file: + bool generateReferenceScreenshot = false; + if(generateReferenceScreenshot) + { + renderingHelper.SaveAsPNG("/home/kilgus/Pictures/RenderingTestData/output.png"); + } + + //### Usage of vtkRegressionTestImage: + //vtkRegressionTestImage( vtkRenderWindow ) + //Set a vtkRenderWindow containing the desired scene. + //vtkRegressionTestImage automatically searches in argc and argv[] + //for a path a valid image with -V. If the test failed with the + //first image (foo.png) check if there are images of the form + //foo_N.png (where N=1,2,3...) and compare against them. + int retVal = vtkRegressionTestImage( renderingHelper.GetVtkRenderWindow() ); + + //retVal meanings: (see VTK/Rendering/vtkTesting.h) + //0 = test failed + //1 = test passed + //2 = test not run + //3 = something with vtkInteraction + MITK_TEST_CONDITION( retVal == 1, "VTK test result positive" ); + + MITK_TEST_END(); +} + diff --git a/Core/Code/Testing/mitkImageVtkMapper2DOpacityTest.cpp b/Core/Code/Testing/mitkImageVtkMapper2DOpacityTest.cpp new file mode 100644 index 0000000000..19bb96972b --- /dev/null +++ b/Core/Code/Testing/mitkImageVtkMapper2DOpacityTest.cpp @@ -0,0 +1,73 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +//MITK +#include "mitkTestingMacros.h" +#include "mitkRenderingTestHelper.h" + +//VTK +#include + + +int mitkImageVtkMapper2DOpacityTest(int argc, char* argv[]) +{ + // load all arguments into a datastorage, take last argument as reference rendering + // setup a renderwindow of fixed size X*Y + // render the datastorage + // compare rendering to reference image + MITK_TEST_BEGIN("mitkImageVtkMapper2DTest") + + // enough parameters? + if ( argc < 2 ) + { + MITK_TEST_OUTPUT( << "Usage: " << std::string(*argv) << " [file1 file2 ...] outputfile" ) + MITK_TEST_OUTPUT( << "Will render a central transversal slice of all given files into outputfile" ) + exit( EXIT_SUCCESS ); + } + + mitkRenderingTestHelper renderingHelper(640, 480, argc, argv); + //Set the opacity for all images + renderingHelper.SetProperty("opacity", mitk::FloatProperty::New(0.5f)); + //for now this test renders in coronal view direction + renderingHelper.SetViewDirection(mitk::SliceNavigationController::Frontal); + renderingHelper.Render(); + + //use this to generate a reference screenshot or save the file: + bool generateReferenceScreenshot = false; + if(generateReferenceScreenshot) + { + renderingHelper.SaveAsPNG("/home/kilgus/Pictures/RenderingTestData/output.png"); + } + + //### Usage of vtkRegressionTestImage: + //vtkRegressionTestImage( vtkRenderWindow ) + //Set a vtkRenderWindow containing the desired scene. + //vtkRegressionTestImage automatically searches in argc and argv[] + //for a path a valid image with -V. If the test failed with the + //first image (foo.png) check if there are images of the form + //foo_N.png (where N=1,2,3...) and compare against them. + int retVal = vtkRegressionTestImage( renderingHelper.GetVtkRenderWindow() ); + + //retVal meanings: (see VTK/Rendering/vtkTesting.h) + //0 = test failed + //1 = test passed + //2 = test not run + //3 = something with vtkInteraction + MITK_TEST_CONDITION( retVal == 1, "VTK test result positive" ); + + MITK_TEST_END(); +} + diff --git a/Core/Code/Testing/mitkImageVtkMapper2DTest.cpp b/Core/Code/Testing/mitkImageVtkMapper2DTest.cpp index f677e9d2af..13f36691b6 100644 --- a/Core/Code/Testing/mitkImageVtkMapper2DTest.cpp +++ b/Core/Code/Testing/mitkImageVtkMapper2DTest.cpp @@ -1,123 +1,69 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - +//MITK #include "mitkTestingMacros.h" - -#include "mitkDataNodeFactory.h" -#include "mitkStandaloneDataStorage.h" - -#include -#include -#include -#include // nice one - -#include -#include - #include "mitkRenderingTestHelper.h" -#include - -class mitkRenderingTestHelperClass -{ - -public: - - static mitk::BaseData::Pointer AddToStorage(const std::string& filename) - { - mitk::DataNodeFactory::Pointer reader = mitk::DataNodeFactory::New(); - try - { - reader->SetFileName( filename ); - reader->Update(); - - if(reader->GetNumberOfOutputs()<1) - { - MITK_TEST_FAILED_MSG(<< "Could not find test data '" << filename << "'"); - } - - mitk::DataNode::Pointer node = reader->GetOutput( 0 ); - mitkRenderingTestHelperClass::s_DataStorage->Add(node); - return node->GetData(); - } - catch ( itk::ExceptionObject & e ) - { - MITK_TEST_FAILED_MSG(<< "Failed loading test data '" << filename << "': " << e.what()); - } - } - - static mitk::DataStorage::Pointer s_DataStorage; -}; // end test helper class +//VTK +#include -mitk::DataStorage::Pointer mitkRenderingTestHelperClass::s_DataStorage; int mitkImageVtkMapper2DTest(int argc, char* argv[]) { // load all arguments into a datastorage, take last argument as reference rendering // setup a renderwindow of fixed size X*Y // render the datastorage // compare rendering to reference image MITK_TEST_BEGIN("mitkImageVtkMapper2DTest") - // enough parameters? - if ( argc < 2 ) + // enough parameters? + if ( argc < 2 ) { MITK_TEST_OUTPUT( << "Usage: " << std::string(*argv) << " [file1 file2 ...] outputfile" ) MITK_TEST_OUTPUT( << "Will render a central transversal slice of all given files into outputfile" ) exit( EXIT_SUCCESS ); } - // parse parameters - std::vector inputFileNames; - for (int i = 1; i < argc-1; ++i) - { - //add everything to a list but -T and -V - std::string tmp = argv[i]; - if((tmp.compare("-T")) && (tmp.compare("-V"))) - { - inputFileNames.push_back( tmp ); - } - } - // std::string outputFileName( argv[argc-1] ); - - // load all input into a data storage - mitkRenderingTestHelperClass::s_DataStorage = mitk::StandaloneDataStorage::New().GetPointer(); - MITK_TEST_CONDITION_REQUIRED(mitkRenderingTestHelperClass::s_DataStorage.IsNotNull(),"StandaloneDataStorage instantiation"); - - std::for_each( inputFileNames.begin(), inputFileNames.end(), mitkRenderingTestHelperClass::AddToStorage ); - - // create a mitkRenderWindow, let it render the scene and get the vtkRenderWindow - mitkRenderingTestHelper renderingHelper( 640, 480, mitkRenderingTestHelperClass::s_DataStorage ); + mitkRenderingTestHelper renderingHelper(640, 480, argc, argv); + renderingHelper.Render(); //use this to generate a reference screenshot or save the file: bool generateReferenceScreenshot = false; if(generateReferenceScreenshot) { renderingHelper.SaveAsPNG("/home/kilgus/Pictures/RenderingTestData/output.png"); } + + //### Usage of vtkRegressionTestImage: + //vtkRegressionTestImage( vtkRenderWindow ) + //Set a vtkRenderWindow containing the desired scene. + //vtkRegressionTestImage automatically searches in argc and argv[] + //for a path a valid image with -V. If the test failed with the + //first image (foo.png) check if there are images of the form + //foo_N.png (where N=1,2,3...) and compare against them. int retVal = vtkRegressionTestImage( renderingHelper.GetVtkRenderWindow() ); //retVal meanings: (see VTK/Rendering/vtkTesting.h) //0 = test failed //1 = test passed //2 = test not run //3 = something with vtkInteraction MITK_TEST_CONDITION( retVal == 1, "VTK test result positive" ); MITK_TEST_END(); } diff --git a/Core/Code/Testing/mitkPlanePositionManagerTest.cpp b/Core/Code/Testing/mitkPlanePositionManagerTest.cpp index c8806d009d..7557d12f19 100644 --- a/Core/Code/Testing/mitkPlanePositionManagerTest.cpp +++ b/Core/Code/Testing/mitkPlanePositionManagerTest.cpp @@ -1,256 +1,271 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkRotationOperation.h" #include "mitkTestingMacros.h" #include "mitkPlanePositionManager.h" #include "mitkSliceNavigationController.h" #include "mitkGeometry3D.h" #include "mitkPlaneGeometry.h" #include "mitkImage.h" #include "mitkSurface.h" #include "mitkStandaloneDataStorage.h" #include "mitkDataNode.h" #include "mitkStringProperty.h" #include "mitkBaseProperty.h" #include "mitkInteractionConst.h" #include "vnl/vnl_vector.h" #include #include "mitkGetModuleContext.h" std::vector m_Geometries; std::vector m_SliceIndices; mitk::PlanePositionManagerService* m_Service; int SetUpBeforeTest() { //Getting Service mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); m_Service = dynamic_cast(mitk::GetModuleContext()->GetService(serviceRef)); if (m_Service == 0) return EXIT_FAILURE; //Creating different Geometries m_Geometries.reserve(100); mitk::PlaneGeometry::PlaneOrientation views[] = {mitk::PlaneGeometry::Transversal, mitk::PlaneGeometry::Sagittal, mitk::PlaneGeometry::Frontal}; for (unsigned int i = 0; i < 100; ++i) { mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); mitk::ScalarType width = 256+(0.01*i); mitk::ScalarType height = 256+(0.002*i); mitk::Vector3D right; mitk::Vector3D down; right[0] = 1; right[1] = i; right[2] = 0.5; down[0] = i*0.02; down[1] = 1; down[2] = i*0.03; mitk::Vector3D spacing; mitk::FillVector3D(spacing, 1.0*0.02*i, 1.0*0.15*i, 1.0); mitk::Vector3D rightVector; mitk::FillVector3D(rightVector, 0.02*(i+1), 0+(0.05*i), 1.0); mitk::Vector3D downVector; mitk::FillVector3D(downVector, 1, 3-0.01*i, 0.0345*i); vnl_vector normal = vnl_cross_3d(rightVector.GetVnlVector(), downVector.GetVnlVector()); normal.normalize(); normal *= 1.5; mitk::Vector3D origin; origin.Fill(1); origin[0] = 12 + 0.03*i; mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New(); mitk::Matrix3D matrix; matrix.GetVnlMatrix().set_column(0, rightVector.GetVnlVector()); matrix.GetVnlMatrix().set_column(1, downVector.GetVnlVector()); matrix.GetVnlMatrix().set_column(2, normal); transform->SetMatrix(matrix); transform->SetOffset(origin); plane->InitializeStandardPlane(width, height, transform, views[i%3], i, true, false); m_Geometries.push_back(plane); } return EXIT_SUCCESS; } int testAddPlanePosition() { MITK_TEST_OUTPUT(<<"Starting Test: ######### A d d P l a n e P o s i t i o n #########"); MITK_TEST_CONDITION(m_Service != NULL, "Testing getting of PlanePositionManagerService"); unsigned int currentID(m_Service->AddNewPlanePosition(m_Geometries.at(0),0)); bool error = ((m_Service->GetNumberOfPlanePositions() != 1)||(currentID != 0)); if(error) { MITK_TEST_CONDITION(m_Service->GetNumberOfPlanePositions() == 1,"Checking for correct number of planepositions"); MITK_TEST_CONDITION(currentID == 0, "Testing for correct ID"); return EXIT_FAILURE; } //Adding new planes for(unsigned int i = 1; i < m_Geometries.size(); ++i) { unsigned int newID = m_Service->AddNewPlanePosition(m_Geometries.at(i),i); error = ((m_Service->GetNumberOfPlanePositions() != i+1)||(newID != (currentID+1))); if (error) { MITK_TEST_CONDITION(m_Service->GetNumberOfPlanePositions() == i+1,"Checking for correct number of planepositions"); MITK_TEST_CONDITION(newID == (currentID+1), "Testing for correct ID"); MITK_TEST_OUTPUT(<<"New: "<GetNumberOfPlanePositions(); //Adding existing planes -> nothing should change for(unsigned int i = 0; i < (m_Geometries.size()-1)*0.5; ++i) { unsigned int newID = m_Service->AddNewPlanePosition(m_Geometries.at(i*2),i*2); error = ((m_Service->GetNumberOfPlanePositions() != numberOfPlanePos)||(newID != i*2)); if (error) { MITK_TEST_CONDITION( m_Service->GetNumberOfPlanePositions() == numberOfPlanePos, "Checking for correct number of planepositions"); MITK_TEST_CONDITION(newID == i*2, "Testing for correct ID"); return EXIT_FAILURE; } } return EXIT_SUCCESS; } int testGetPlanePosition() { mitk::PlaneGeometry* plane; mitk::RestorePlanePositionOperation* op; bool error(true); MITK_TEST_OUTPUT(<<"Starting Test: ######### G e t P l a n e P o s i t i o n #########"); //Testing for existing planepositions for (unsigned int i = 0; i < m_Geometries.size(); ++i) { plane = m_Geometries.at(i); op = m_Service->GetPlanePosition(i); error = ( !mitk::Equal(op->GetHeight(),plane->GetExtent(1)) || !mitk::Equal(op->GetWidth(),plane->GetExtent(0)) || !mitk::Equal(op->GetSpacing(),plane->GetSpacing()) || !mitk::Equal(op->GetTransform()->GetOffset(),plane->GetIndexToWorldTransform()->GetOffset()) || !mitk::Equal(op->GetDirectionVector().Get_vnl_vector(),plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).normalize()) || !mitk::MatrixEqualElementWise(op->GetTransform()->GetMatrix(), plane->GetIndexToWorldTransform()->GetMatrix()) ); if( error ) { MITK_TEST_OUTPUT(<<"Iteration: "<GetHeight(),plane->GetExtent(1)) && mitk::Equal(op->GetWidth(),plane->GetExtent(0)), "Checking for correct extent"); MITK_TEST_CONDITION( mitk::Equal(op->GetSpacing(),plane->GetSpacing()), "Checking for correct spacing"); MITK_TEST_CONDITION( mitk::Equal(op->GetTransform()->GetOffset(),plane->GetIndexToWorldTransform()->GetOffset()), "Checking for correct offset"); MITK_INFO<<"Op: "<GetDirectionVector()<<" plane: "<GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)<<"\n"; MITK_TEST_CONDITION( mitk::Equal(op->GetDirectionVector().Get_vnl_vector(),plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)), "Checking for correct direction"); MITK_TEST_CONDITION( mitk::MatrixEqualElementWise(op->GetTransform()->GetMatrix(), plane->GetIndexToWorldTransform()->GetMatrix()), "Checking for correct matrix"); return EXIT_FAILURE; } } //Testing for not existing planepositions error = ( m_Service->GetPlanePosition(100000000) != 0 || m_Service->GetPlanePosition(-1) != 0 ); if (error) { MITK_TEST_CONDITION(m_Service->GetPlanePosition(100000000) == 0, "Trying to get non existing pos"); MITK_TEST_CONDITION(m_Service->GetPlanePosition(-1) == 0, "Trying to get non existing pos"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int testRemovePlanePosition() { MITK_TEST_OUTPUT(<<"Starting Test: ######### R e m o v e P l a n e P o s i t i o n #########"); unsigned int size = m_Service->GetNumberOfPlanePositions(); bool removed (true); //Testing for invalid IDs removed = m_Service->RemovePlanePosition( -1 ); removed = m_Service->RemovePlanePosition( 1000000 ); unsigned int size2 = m_Service->GetNumberOfPlanePositions(); if (removed) { MITK_TEST_CONDITION(removed == false, "Testing remove not existing planepositions"); MITK_TEST_CONDITION(size == size2, "Testing remove not existing planepositions"); return EXIT_FAILURE; } //Testing for valid IDs for (unsigned int i = 0; i < m_Geometries.size()*0.5; i++) { removed = m_Service->RemovePlanePosition( i ); unsigned int size2 = m_Service->GetNumberOfPlanePositions(); removed = (size2 == (size-(i+1))); if (!removed) { MITK_TEST_CONDITION(removed == true, "Testing remove existing planepositions"); MITK_TEST_CONDITION(size == (size-i+1), "Testing remove existing planepositions"); return EXIT_FAILURE; } } return EXIT_SUCCESS; } int testRemoveAll() { MITK_TEST_OUTPUT(<<"Starting Test: ######### R e m o v e A l l #########"); unsigned int numPos = m_Service->GetNumberOfPlanePositions(); MITK_INFO<RemoveAllPlanePositions(); bool error (true); error = (m_Service->GetNumberOfPlanePositions() != 0 || m_Service->GetPlanePosition(60) != 0); if (error) { MITK_TEST_CONDITION(m_Service->GetNumberOfPlanePositions() == 0, "Testing remove all pos"); MITK_TEST_CONDITION(m_Service->GetPlanePosition(60) == 0, "Testing remove all pos"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int mitkPlanePositionManagerTest(int, char* []) { MITK_TEST_OUTPUT(<<"Starting Test PlanePositionManager"); SetUpBeforeTest(); int result; MITK_TEST_CONDITION_REQUIRED( (result = testAddPlanePosition()) == EXIT_SUCCESS, ""); MITK_TEST_CONDITION_REQUIRED( (result = testGetPlanePosition()) == EXIT_SUCCESS, ""); MITK_TEST_CONDITION_REQUIRED( (result = testRemovePlanePosition()) == EXIT_SUCCESS, ""); MITK_TEST_CONDITION_REQUIRED( (result = testRemoveAll()) == EXIT_SUCCESS, ""); return EXIT_SUCCESS; } diff --git a/Core/Code/Testing/mitkRenderingTestHelper.cpp b/Core/Code/Testing/mitkRenderingTestHelper.cpp index 98fce2fd8d..216c7cdd1b 100644 --- a/Core/Code/Testing/mitkRenderingTestHelper.cpp +++ b/Core/Code/Testing/mitkRenderingTestHelper.cpp @@ -1,87 +1,145 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderingTestHelper.h" -#include "mitkStandaloneDataStorage.h" +#include #include #include #include -#include +#include #include -#include #include #include -#include -mitkRenderingTestHelper::mitkRenderingTestHelper(int width, int height, mitk::DataStorage *ds) +mitkRenderingTestHelper::mitkRenderingTestHelper(int width, int height, int argc, char* argv[]) { - // Global interaction must(!) be initialized - mitk::GlobalInteraction::GetInstance()->Initialize("global"); + // Global interaction must(!) be initialized + mitk::GlobalInteraction::GetInstance()->Initialize("global"); - m_RenderWindow = mitk::RenderWindow::New(); - m_RenderWindow->GetRenderer()->SetDataStorage(ds); - m_RenderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); - this->GetVtkRenderWindow()->SetSize( width, height ); + m_DataStorage = mitk::StandaloneDataStorage::New(); - mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Transversal); - mitk::TimeSlicedGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); + m_RenderWindow = mitk::RenderWindow::New(); + m_RenderWindow->GetRenderer()->SetDataStorage(m_DataStorage); + m_RenderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); + this->GetVtkRenderWindow()->SetSize( width, height ); + this->SetInputFileNames(argc, argv); +} - //Level Window Property -// ds->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(254.0, 1.0) ) ); +mitkRenderingTestHelper::~mitkRenderingTestHelper() +{ +} - mitk::RenderingManager::GetInstance()->InitializeViews( geo ); - mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetVtkRenderWindow()); +void mitkRenderingTestHelper::Render() +{ + //if the datastorage is initialized and at least 1 image is loaded render it + if(m_DataStorage.IsNotNull() || m_DataStorage->GetAll()->Size() >= 1 ) + { + mitk::TimeSlicedGeometry::Pointer geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()); + + mitk::RenderingManager::GetInstance()->InitializeViews( geo ); + mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetVtkRenderWindow()); + } + else + { + MITK_ERROR << "No images loaded in data storage!"; + } + + //use this to actually show the iamge in a renderwindow + // this->GetVtkRenderWindow()->Render(); + // this->GetVtkRenderWindow()->GetInteractor()->Start(); +} -//use this to actually show the iamge in a renderwindow -// this->GetVtkRenderWindow()->Render(); -// this->GetVtkRenderWindow()->GetInteractor()->Start(); +void mitkRenderingTestHelper::SetInputFileNames(int argc, char* argv[]) +{ + // parse parameters + for (int i = 1; i < argc; ++i) + { + //add everything to a list but -T and -V + std::string tmp = argv[i]; + if((tmp.compare("-T")) && (tmp.compare("-V"))) + { + this->AddToStorage(tmp); + } + else + { + break; + } + } } -mitkRenderingTestHelper::~mitkRenderingTestHelper() +void mitkRenderingTestHelper::SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection) { + mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); } vtkRenderer* mitkRenderingTestHelper::GetVtkRenderer() { - return m_RenderWindow->GetRenderer()->GetVtkRenderer(); + return m_RenderWindow->GetRenderer()->GetVtkRenderer(); +} + +void mitkRenderingTestHelper::SetProperty(const char *propertyKey, mitk::BaseProperty* property ) +{ + this->m_DataStorage->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty(propertyKey, property); } vtkRenderWindow* mitkRenderingTestHelper::GetVtkRenderWindow() { - return m_RenderWindow->GetVtkRenderWindow(); + return m_RenderWindow->GetVtkRenderWindow(); } //method to save a screenshot of the renderwindow (e.g. create a reference screenshot) void mitkRenderingTestHelper::SaveAsPNG(std::string fileName) { - vtkSmartPointer renderer = this->GetVtkRenderer(); - bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); - renderer->GetRenderWindow()->DoubleBufferOff(); + vtkSmartPointer renderer = this->GetVtkRenderer(); + bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); + renderer->GetRenderWindow()->DoubleBufferOff(); + + vtkSmartPointer magnifier = vtkSmartPointer::New(); + magnifier->SetInput(renderer); + magnifier->SetMagnification(1.0); - vtkSmartPointer magnifier = vtkSmartPointer::New(); - magnifier->SetInput(renderer); - magnifier->SetMagnification(1.0); + vtkSmartPointer fileWriter = vtkSmartPointer::New(); + fileWriter->SetInput(magnifier->GetOutput()); + fileWriter->SetFileName(fileName.c_str()); - vtkSmartPointer fileWriter = vtkSmartPointer::New(); - fileWriter->SetInput(magnifier->GetOutput()); - fileWriter->SetFileName(fileName.c_str()); + fileWriter->Write(); + renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); +} - fileWriter->Write(); - renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); +void mitkRenderingTestHelper::AddToStorage(const std::string &filename) +{ + mitk::DataNodeFactory::Pointer reader = mitk::DataNodeFactory::New(); + try + { + reader->SetFileName( filename ); + reader->Update(); + + if(reader->GetNumberOfOutputs()<1) + { + MITK_ERROR << "Could not find test data '" << filename << "'"; + } + + mitk::DataNode::Pointer node = reader->GetOutput( 0 ); + this->m_DataStorage->Add(node); + } + catch ( itk::ExceptionObject & e ) + { + MITK_ERROR << "Failed loading test data '" << filename << "': " << e.what(); + } } diff --git a/Core/Code/Testing/mitkRenderingTestHelper.h b/Core/Code/Testing/mitkRenderingTestHelper.h index f8790f561e..fdac395dd2 100644 --- a/Core/Code/Testing/mitkRenderingTestHelper.h +++ b/Core/Code/Testing/mitkRenderingTestHelper.h @@ -1,50 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRenderingTestHelper_h #define mitkRenderingTestHelper_h -#include #include -#include #include +#include +#include class vtkRenderWindow; class vtkRenderer; -namespace mitk -{ - class DataStorage; -} - class mitkRenderingTestHelper { - public: - mitkRenderingTestHelper(int width, int height, mitk::DataStorage* ds); + +public: + /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel). + @param argc Number of parameters. (here: Images) "Usage: [filename1 filenam2 -V referenceScreenshot (optional -T /directory/to/save/differenceImage)] + @param argv Given parameters. + **/ + mitkRenderingTestHelper(int width, int height, int argc, char *argv[]); ~mitkRenderingTestHelper(); + /** @brief Getter for the vtkRenderer. + **/ vtkRenderer* GetVtkRenderer(); + + /** @brief Getter for the vtkRenderWindow which should be used to call vtkRegressionTestImage. + **/ vtkRenderWindow* GetVtkRenderWindow(); + + /** @brief Method can be used to save a screenshot (e.g. reference screenshot as a .png file. + @param fileName The filename of the new screenshot (including path). + **/ void SaveAsPNG(std::string fileName); - protected: - mitk::RenderWindow::Pointer m_RenderWindow; + /** @brief This method set the property of the member datastorage + @param property Set a property for each image in the datastorage m_DataStorage. + **/ + void SetProperty(const char *propertyKey, mitk::BaseProperty *property); + + /** @brief Set the view direction of the renderwindow (e.g. sagittal, coronal, transversal) + **/ + void SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection); + + /** @brief Render everything into an mitkRenderWindow. Call SetViewDirection() and SetProperty() before this method. + **/ + void Render(); +protected: + + /** @brief This method tries to load the given file into a member datastorage, in order to render it. + @param fileName The filename of the file to be loaded (including path). + **/ + void AddToStorage(const std::string& filename); + + /** @brief This method tries to parse the given argv for files (e.g. images) and load them into a member datastorage, in order to render it. + @param argc Number of parameters. + @param argv Given parameters. + **/ + void SetInputFileNames(int argc, char *argv[]); + + mitk::RenderWindow::Pointer m_RenderWindow; //<< Contains the mitkRenderWindow into which the test renders the data + mitk::DataStorage::Pointer m_DataStorage; //<< Contains the mitkDataStorage which contains the data to be rendered }; #endif diff --git a/Core/Code/Testing/uServicesBaseObject.h b/Core/Code/Testing/uServicesBaseObject.h index fc0cfe61d0..8619b6f998 100644 --- a/Core/Code/Testing/uServicesBaseObject.h +++ b/Core/Code/Testing/uServicesBaseObject.h @@ -1,11 +1,26 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef USERVICESBASEOBJECT_H #define USERVICESBASEOBJECT_H #include #include template<> inline const char* us_service_impl_name(itk::LightObject* impl) { return impl->GetNameOfClass(); } #endif // USERVICESBASEOBJECT_H diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake index 7982bf5875..d2d4b34679 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,300 +1,302 @@ set(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkLocalVariationImageFilter.h Algorithms/itkLocalVariationImageFilter.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/itkTotalVariationDenoisingImageFilter.h Algorithms/itkTotalVariationDenoisingImageFilter.txx Algorithms/itkTotalVariationSingleIterationImageFilter.h Algorithms/itkTotalVariationSingleIterationImageFilter.txx Algorithms/mitkBilateralFilter.h Algorithms/mitkBilateralFilter.cpp Algorithms/mitkImageAccessByItk.h Algorithms/mitkImageCast.h Algorithms/mitkImageToItk.h Algorithms/mitkImageToItk.txx Algorithms/mitkInstantiateAccessFunctions.h Algorithms/mitkITKImageImport.h Algorithms/mitkITKImageImport.txx Algorithms/mitkPixelTypeList.h # Preprocessor macros taken from Boost Algorithms/mitkPPArithmeticDec.h Algorithms/mitkPPArgCount.h Algorithms/mitkPPCat.h Algorithms/mitkPPConfig.h Algorithms/mitkPPControlExprIIf.h Algorithms/mitkPPControlIf.h Algorithms/mitkPPControlIIf.h Algorithms/mitkPPDebugError.h Algorithms/mitkPPDetailAutoRec.h Algorithms/mitkPPDetailDMCAutoRec.h Algorithms/mitkPPExpand.h Algorithms/mitkPPFacilitiesEmpty.h Algorithms/mitkPPFacilitiesExpand.h Algorithms/mitkPPLogicalBool.h Algorithms/mitkPPRepetitionDetailDMCFor.h Algorithms/mitkPPRepetitionDetailEDGFor.h Algorithms/mitkPPRepetitionDetailFor.h Algorithms/mitkPPRepetitionDetailMSVCFor.h Algorithms/mitkPPRepetitionFor.h Algorithms/mitkPPSeqElem.h Algorithms/mitkPPSeqForEach.h Algorithms/mitkPPSeqForEachProduct.h Algorithms/mitkPPSeq.h Algorithms/mitkPPSeqEnum.h Algorithms/mitkPPSeqSize.h Algorithms/mitkPPSeqToTuple.h Algorithms/mitkPPStringize.h Algorithms/mitkPPTupleEat.h Algorithms/mitkPPTupleElem.h Algorithms/mitkPPTupleRem.h Algorithms/mitkClippedSurfaceBoundsCalculator.h - + Algorithms/mitkExtractSliceFilter.h + Interfaces/mitkIDataNodeReader.h IO/mitkPixelTypeTraits.h DataManagement/mitkCommon.h Interactions/mitkEventMapperAddOn.h Common/mitkExceptionMacro.h ) set(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkBaseProcess.cpp Algorithms/mitkCoreObjectFactoryBase.cpp Algorithms/mitkCoreObjectFactory.cpp Algorithms/mitkDataNodeFactory.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageCaster.cpp Algorithms/mitkImageCastPart1.cpp Algorithms/mitkImageCastPart2.cpp Algorithms/mitkImageCastPart3.cpp Algorithms/mitkImageCastPart4.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp + Algorithms/mitkExtractSliceFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkCoreActivator.cpp Controllers/mitkFocusManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkSlicesRotator.cpp Controllers/mitkSlicesSwiveller.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkInteractorCameraController.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataStorage.cpp #DataManagement/mitkDataTree.cpp DataManagement/mitkDataNode.cpp #DataManagement/mitkDataTreeStorage.cpp DataManagement/mitkDisplayGeometry.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkGeometry2D.cpp DataManagement/mitkGeometry2DData.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkLandmarkBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModeOperation.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStateTransitionOperation.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeSlicedGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkVector.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkShaderProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkMaterial.cpp Interactions/mitkAction.cpp Interactions/mitkAffineInteractor.cpp Interactions/mitkCoordinateSupplier.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkDisplayPositionEvent.cpp Interactions/mitkDisplayVectorInteractor.cpp Interactions/mitkDisplayVectorInteractorLevelWindow.cpp Interactions/mitkDisplayVectorInteractorScroll.cpp Interactions/mitkEvent.cpp Interactions/mitkEventDescription.cpp Interactions/mitkEventMapper.cpp Interactions/mitkGlobalInteraction.cpp Interactions/mitkInteractor.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMovePointSetInteractor.cpp Interactions/mitkMoveSurfaceInteractor.cpp Interactions/mitkNodeDepententPointSetInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Interactions/mitkState.cpp Interactions/mitkStateEvent.cpp Interactions/mitkStateMachine.cpp Interactions/mitkStateMachineFactory.cpp Interactions/mitkTransition.cpp Interactions/mitkWheelEvent.cpp Interactions/mitkKeyEvent.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkCrosshairPositionEvent.cpp IO/mitkBaseDataIOFactory.cpp IO/mitkCoreDataNodeReader.cpp IO/mitkDicomSeriesReader.cpp IO/mitkFileReader.cpp IO/mitkFileSeriesReader.cpp IO/mitkFileWriter.cpp #IO/mitkIpPicGet.c IO/mitkImageGenerator.cpp IO/mitkImageWriter.cpp IO/mitkImageWriterFactory.cpp IO/mitkItkImageFileIOFactory.cpp IO/mitkItkImageFileReader.cpp IO/mitkItkPictureWrite.cpp IO/mitkIOUtil.cpp IO/mitkLookupTableProperty.cpp IO/mitkOperation.cpp #IO/mitkPicFileIOFactory.cpp #IO/mitkPicFileReader.cpp #IO/mitkPicFileWriter.cpp #IO/mitkPicHelper.cpp #IO/mitkPicVolumeTimeSeriesIOFactory.cpp #IO/mitkPicVolumeTimeSeriesReader.cpp IO/mitkPixelType.cpp IO/mitkPointSetIOFactory.cpp IO/mitkPointSetReader.cpp IO/mitkPointSetWriter.cpp IO/mitkPointSetWriterFactory.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSTLFileIOFactory.cpp IO/mitkSTLFileReader.cpp IO/mitkSurfaceVtkWriter.cpp IO/mitkSurfaceVtkWriterFactory.cpp IO/mitkVtiFileIOFactory.cpp IO/mitkVtiFileReader.cpp IO/mitkVtkImageIOFactory.cpp IO/mitkVtkImageReader.cpp IO/mitkVtkSurfaceIOFactory.cpp IO/mitkVtkSurfaceReader.cpp IO/vtkPointSetXMLParser.cpp IO/mitkLog.cpp Rendering/mitkBaseRenderer.cpp Rendering/mitkVtkMapper2D.cpp Rendering/mitkVtkMapper3D.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkGeometry2DDataMapper2D.cpp Rendering/mitkGeometry2DDataVtkMapper3D.cpp Rendering/mitkGLMapper2D.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkManufacturerLogo.cpp Rendering/mitkMapper2D.cpp Rendering/mitkMapper3D.cpp Rendering/mitkMapper.cpp Rendering/mitkPointSetGLMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkPolyDataGLMapper2D.cpp Rendering/mitkSurfaceGLMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVolumeDataVtkMapper3D.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkShaderRepository.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkMitkApplyLevelWindowToRGBFilter.cpp Common/mitkException.cpp ) list(APPEND CPP_FILES ${CppMicroServices_SOURCES}) diff --git a/Core/Documentation/Doxygen/Concepts/Concepts.dox b/Core/Documentation/Doxygen/Concepts/Concepts.dox index e2477919d5..4caf8cec74 100644 --- a/Core/Documentation/Doxygen/Concepts/Concepts.dox +++ b/Core/Documentation/Doxygen/Concepts/Concepts.dox @@ -1,15 +1,17 @@ /** \page Concepts MITK concepts The following items describe some issues about MITK on a more abstract level. If you want to start using MITK, you also want to see \ref Development -\li \subpage GeometryOverviewPage -\li \subpage InteractionPage \li \subpage OverviewPage -\li \subpage MicroServices_Overview -\li \subpage PropertiesPage \li \subpage QVTKRendering +\li \subpage InteractionPage +\li \subpage ExceptionPage +\li \subpage LoggingPage +\li \subpage PropertiesPage +\li \subpage GeometryOverviewPage +\li \subpage MicroServices_Overview \li \subpage RenderingTests */ diff --git a/Core/Documentation/Doxygen/Concepts/Exceptions.dox b/Core/Documentation/Doxygen/Concepts/Exceptions.dox new file mode 100644 index 0000000000..e3f3149380 --- /dev/null +++ b/Core/Documentation/Doxygen/Concepts/Exceptions.dox @@ -0,0 +1,92 @@ +/** +\page ExceptionPage Error Handling and Exception Concept + +\ref ExceptionHandling "1. General Exception Handling" + +\ref SpecializedExceptionHandling "2. Defining and Using Specialized Exceptions" + +\section ExceptionHandling General Exception Handling + +In MITK, errors during program execution are handled by the well known exception handling concept which is part of the C++ language. In case of unexpected exceptional behaviour or errors during program execution MITK classes throw exceptions. MITK exceptions are always objects of the class mitk::Exception or of one of its subclasses. + +\subsection Throw Throwing of exceptions + +Exceptions should always be thrown by using the predefined exception macros. If you want to throw a mitk::Exception in your code, simply use the following macro. + +\verbatim +//This command will throw a mitk::Exception and add a message. +//The macro will also add filename and line number to the exception +//object. +mitkThrow() << "Here comes your exception message"; +\endverbatim + +You can also stream more complex messages, e.g. adding integers or other variables to your exception messages, like shown in the following example. + +\verbatim +mitkThrow() << "This time we show the values of some variables:" << m_MyObject->GetSize() << m_MyInteger; +\endverbatim + +\subsection Doc Documentation of exceptions + +If you throw exceptions in your code, please also document this in your doxygen comments by using the "@throws " tag. This will help users of your class to catch and handle the exceptions in a proper way. An example how to document exception throwing is given below. + +\verbatim +class myExampleClass + { + + /** Documentation + * @brief This method does [...] + * @throws mitk::Exception This exception is thrown, when the following error occures: [...] + */ + + void MyExampleMethod() + { + //here comes your code + + //here happens an exception + mitkThrow() << "An exception occured because [...], method can't continue."; + } + } +\endverbatim + +In general, exceptions emit no logging messages by default because they are intended to be catched by overlying classes. This classes should then decide what to do, e.g. to log an error message or handle the exception in another way. See the logging documentation for more details on error logging. + +\subsection Catch Catching exceptions + +Exceptions should be catched by overlying classes, when they can handle them in a proper way. Catching exceptions is very simple, use the standard try-catch block to do so. An example is given below. + +\verbatim +try + { + //call of a method which may throw an exception + myObject->MyExampleMethod(); + } +catch (mitk::Exception e) + { + //This code is executed if an exception of the given type was thrown above. + //For example log an error message here or do some other proper handling of the exception. + } +\endverbatim + +Please do not use "catch (...)" because normally your class can't garantee to handle all exceptions in a proper way without differentiate them. + +\section SpecializedExceptionHandling Defining and Using more Specialized Exceptions + +The basic MITK exception concept was kept very simple and should suffice in many cases. But you can also use more specialized exceptions, if needed. Nevertheless all MITK exceptions should be subclasses of mitk::exception. You can define your own exception classes by simply implementing new classes which derive from mitk::exception. Thus, you can catch your exception seperately when needed. The mitkExceptionClassMacro helps to keep implementing new exception classes as simple as possible, like shown in the following code example. + +\verbatim +#include + +class mitk::MySpecializedException : public mitk::Exception + { + public: + mitkExceptionClassMacro(mitk::MySpecializedException,mitk::Exception); + }; +\endverbatim + +To throw your specialized exception you should use the corresponing macro, which is shown in the next code snippet. + +\verbatim +mitkThrowException(mitk::MySpecializedException) << "this is error info"; +\endverbatim +*/ \ No newline at end of file diff --git a/Core/Documentation/Doxygen/Concepts/Logging.dox b/Core/Documentation/Doxygen/Concepts/Logging.dox new file mode 100644 index 0000000000..de6aef863d --- /dev/null +++ b/Core/Documentation/Doxygen/Concepts/Logging.dox @@ -0,0 +1,78 @@ +/** +\page LoggingPage Logging Concept + +Available sections: + +-# \ref Sec1 "Basic Information on Logging" +-# \ref Sec2 "Categorize your Logging Messages" +-# \ref Sec3 "Logging Levels" +-# \ref Sec4 "Conditional Logging" + + +\section Sec1 Basic Information on Logging +To use logging in MITK you can stream your messages into a logging stream, similar to the "std::cout" stream in standard c++. A simple example is shown next. +\code +MITK_INFO << "Here comes my message"; +\endcode +Please only use the MITK_INFO (respectively MITK_WARN, MITK_ERROR, MITK_FATAL, MITK_DEBUG, see section "Logging levels" for more details) in MITK, the std::cout stream should not be used. +You can also log object information, like shown in the next example. +\code +MITK_INFO << "I want to log my vector size: " << m_vector.getSize(); +\endcode +All logged information will be displayed in the console and be written to a logging file in the MITK binary folder. Advanced users may want to know that this behavior is controlled by the logging backend class, which can be adapted if you want to change the behavior. +This is everything you need to know about simple logging. Further reading will show you how you can categorize your logging message and what logging levels are. + +\section Sec2 Categorize your Logging Messages +You may also want to categorize your logging messages, so you can assign messages to your specific topic. You can simply add classes and subclasses to your MITK logging messages by using brackets, like shown in the next example. +\code +MITK_INFO << "no class"; +MITK_INFO("MyClass") << "single class"; +MITK_INFO("MyClass")("MySubClass") << "class with subclass"; +\endcode +This classes makes it easy to e.g. simply filter all logging messages only for relevant information. + +\section Sec3 Logging Levels +MITK offers different logging levels. You may mostly want to use MITK_INFO, but please consider using the other levels, e.g. when logging debug information or errors. + +Debug (MITK_DEBUG): These messages are designed for debug output, used to debug your source code. They are only displayed if you turn the CMake-Variable MBILOG_ENABLE_DEBUG_MESSAGES on. You can also use the debug message in release mode, output only depends on the CMake-Variable. + +Example: +\code +MITK_DEBUG << "Result of method LoadPicture(): true." +\endcode + +Info (MITK_INFO): For standard information messages that inform about expected changes/results in the program flow. Info messages should be important and understandable for the users of the program. + +Example: +\code +MITK_INFO << "The picture test.pic has been loaded successfully." +\endcode + +Warning (MITK_WARN): Warning messages should inform about unexpected or potentially problematic states in the program flow that do not lead directly to an error. Thus, after a warning the program should be able continue without errors and in a clear state. + +Example: +\code +MITK_WARN << "The picture test.pic was not loaded because access was denied." +\endcode + +Error (MITK_ERROR): Error messages notify the user about corrupt states in the program flow. Such states may occur after unexpected behavior of source code. + +Example: +\code +MITK_ERROR << "Error while adding test.pic to the data storage, aborting." +\endcode + +Fatal (MITK_FATAL): Fatal messages report corrupt states in the program flow that lead directly to a crash of the program. + +Example: +\code +MITK_FATAL << "Memory allocation error during instantiation of image object." +\endcode + +\section Sec4 Conditional Logging +Another feature of the logging mechanism is that you can directly give conditions if your message should be logged. These bool values or expressions can be defined in brackets. An example is shown next. +\code +MITK_INFO(x>1000) << "x is too large"; //logs only if x > 1000 +\endcode + +*/ \ No newline at end of file diff --git a/Documentation/CMakeLists.txt b/Documentation/CMakeLists.txt index 9ea907bf5a..b64686269f 100644 --- a/Documentation/CMakeLists.txt +++ b/Documentation/CMakeLists.txt @@ -1,175 +1,174 @@ # # Variables: # MITK_DOXYGEN_OUTPUT_DIR: doxygen output directory (optional) # Compile source code snippets #add_subdirectory(Snippets) find_package(Doxygen) if(DOXYGEN_FOUND) option(USE_DOT "Use dot program for generating graphical class diagrams with doxygen, if available" ON) option(MITK_DOXYGEN_BUILD_ALWAYS "Always build the MITK documentation when building the default target" OFF) option(MITK_DOXYGEN_GENERATE_QCH_FILES "Use doxygen to generate Qt compressed help files for MITK docs" OFF) mark_as_advanced(USE_DOT MITK_DOXYGEN_BUILD_ALWAYS MITK_DOXYGEN_GENERATE_QCH_FILES) set(HAVE_DOT "NO") if(DOXYGEN_DOT_EXECUTABLE AND USE_DOT) set(HAVE_DOT "YES") endif() set(MITK_DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/Documentation/Doxygen CACHE PATH "Output directory for doxygen generated documentation." ) set(MITK_DOXYGEN_TAGFILE_NAME ${MITK_DOXYGEN_OUTPUT_DIR}/MITK.tag CACHE INTERNAL "MITK Doxygen tag file") # This is relative to the working directory of the doxygen command set(MITK_DOXYGEN_STYLESHEET mitk_doxygen.css) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${MITK_DOXYGEN_STYLESHEET} ${CMAKE_CURRENT_BINARY_DIR}/${MITK_DOXYGEN_STYLESHEET} @COPYONLY) # Create QCH files for MITK and external projects set(MITK_DOXYGEN_GENERATE_QHP "NO") if(MITK_DOXYGEN_GENERATE_QCH_FILES) find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt4 qhelpgenerator4 PATHS ${QT_BINARY_DIR} DOC "The location of the the Qt help generator executable" NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE) if(NOT QT_HELPGENERATOR_EXECUTABLE) message(SEND_ERROR "The Qt help generator could not be found. Disabling qch generation") else() set(MITK_DOXYGEN_GENERATE_QHP "YES") endif() # The name of the generated MITK qch file, relative to the # Doxygen HTML output folder set(MITK_DOXYGEN_QCH_FILE "${MITK_BINARY_DIR}/MITK-${MITK_REVISION_ID}.qch") # Generating ITK and VTK docs it not done yet #option(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE "Use doxygen to generate a Qt compressed help file for VTK docs" OFF) #option(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE "Use doxygen to generate a Qt compressed help file for ITK docs" OFF) #mark_as_advanced(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) endif() if(MITK_USE_BLUEBERRY) file(RELATIVE_PATH _blueberry_doxygen_path ${MITK_DOXYGEN_OUTPUT_DIR}/html ${BLUEBERRY_DOXYGEN_OUTPUT_DIR}/html) set(BLUEBERRY_DOXYGEN_TAGFILE "${BLUEBERRY_DOXYGEN_TAGFILE_NAME}=${_blueberry_doxygen_path}") set(BLUEBERRY_DOXYGEN_LINK "BlueBerry Documentation") set(MITK_XP_LINK "\\ref mitkExtPointsIndex") configure_file(schema.css ${MITK_DOXYGEN_OUTPUT_DIR}/html/schema.css) set(MITK_DOXYGEN_ENABLED_SECTIONS "${MITK_DOXYGEN_ENABLED_SECTIONS} BLUEBERRY") endif(MITK_USE_BLUEBERRY) # Compile a doxygen input filter for processing CMake scripts include(mitkFunctionCMakeDoxygenFilterCompile) mitkFunctionCMakeDoxygenFilterCompile(NAMESPACE "CMake") # Configure some doxygen options if(NOT MITK_DOXYGEN_INTERNAL_DOCS) set(MITK_DOXYGEN_INTERNAL_DOCS "NO") set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "YES") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "*_p.* *Private.h */internal/*") else() set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "NO") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "") endif() if(NOT MITK_DOXYGEN_GENERATE_TODOLIST) set(MITK_DOXYGEN_GENERATE_TODOLIST "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_BUGLIST) set(MITK_DOXYGEN_GENERATE_BUGLIST "NO") endif() if(NOT MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS) set(MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS "NO") endif() if(NOT MITK_DOXYGEN_UML_LOOK) set(MITK_DOXYGEN_UML_LOOK "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_DEPRECATEDLIST) set(MITK_DOXYGEN_GENERATE_DEPRECATEDLIST "YES") endif() if(NOT DEFINED MITK_DOXYGEN_DOT_NUM_THREADS) set(MITK_DOXYGEN_DOT_NUM_THREADS 0) endif() configure_file(Doxygen/MainPage.dox.in ${CMAKE_CURRENT_BINARY_DIR}/Doxygen/MainPage.dox) configure_file(doxygen.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf) if(MITK_DOXYGEN_BUILD_ALWAYS) set(_doc_in_all "ALL") else() set(_doc_in_all "") endif() add_custom_target(doc ${_doc_in_all} ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) if(MITK_USE_BLUEBERRY) # convert the extension points schema files into html find_package(Ant) if(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) list(APPEND MITK_XP_GLOB_EXPRESSIONS - ${MITK_SOURCE_DIR}/CoreUI/Bundles/plugin.xml - ${MITK_SOURCE_DIR}/Modules/Bundles/plugin.xml) + ${MITK_SOURCE_DIR}/Plugins/plugin.xml) file(GLOB_RECURSE _plugin_xmls ${MITK_XP_GLOB_EXPRESSIONS}) MACRO_CONVERT_SCHEMA(INPUT ${_plugin_xmls} OUTPUT_DIR "${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html" TARGET_NAME mitkXPDoc ) add_dependencies(doc mitkXPDoc) if(${PROJECT_NAME} STREQUAL "MITK") add_dependencies(doc BlueBerryDoc) endif() endif(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) endif(MITK_USE_BLUEBERRY) #if(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) # # add the command to generate the ITK documantation # add_custom_target(doc-itk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.itk.conf) # add_dependencies(doc doc-itk) #endif() #if(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE) # # add the command to generate the VTK documantation # add_custom_target(doc-vtk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.vtk.conf) # add_dependencies(doc doc-vtk) #endif() else(DOXYGEN_FOUND) # copy blank documentation page to prevent QtHelp from being shown # copy the .qhc and .qch files to $MITK_BIN/mitk/bin/ExtBundles/resources/ configure_file(pregenerated/MITKBlankPage.qch ${MITK_BINARY_DIR}/bin/ExtBundles/org.mitk.gui.qt.extapplication/resources/MITKBlankPage.qch COPYONLY) configure_file(pregenerated/MitkExtQtHelpCollection.qhc ${MITK_BINARY_DIR}/bin/ExtBundles/org.mitk.gui.qt.extapplication/resources/MitkExtQtHelpCollection.qhc COPYONLY) endif(DOXYGEN_FOUND) diff --git a/Documentation/Doxygen/DeveloperManual/BuildInstructions.dox b/Documentation/Doxygen/DeveloperManual/BuildInstructions.dox index 1c503a8c61..5e68094b90 100644 --- a/Documentation/Doxygen/DeveloperManual/BuildInstructions.dox +++ b/Documentation/Doxygen/DeveloperManual/BuildInstructions.dox @@ -1,201 +1,187 @@ /** \page BuildInstructionsPage Build Instructions \section BuildInstructions_Introduction Introduction The MITK build system (which is based on CMake) supports a "superbuild" process, meaning that it will download, configure, and build all required third-party libraries (except Qt) automatically. These instructions will show you how to use the MITK superbuild. \note This page explains explicitly how to build MITK itself. If you want to create your own project based on MITK, the process described below is completely automated. Please see Setup a MITK-based project For more advanced users, the last sections explain how to inject custom build libraries into the superbuild process. \section BuildInstructions_Prerequisites Prerequisites You need: -# Git from http://git-scm.com (there are also numerous third-party graphical clients available). We recomment using Git, but see below for a way how to get the current source code without using it. -# CMake (version 2.8.4 or higher) -# Qt 4.x if you plan to develop Qt-based applications (version 4.6 or above is recommended, we cannot guarantee compatibility with lower versions) \section BuildInstructions_Qt A note about Qt Nokia provides several binary packages for Qt. You must make sure that the package you download matches your toolchain. On Linux, getting Qt by installing the packages provided by your Linux package manager is the preferred way. On Windows, the Nokia provided binaries are compiled for 32bit architectures. You cannot build your own project for a 64bit machine and use the 32bit Qt libraries. You have two options for a 64bit Qt-based application: -# Download an inofficial 64bit installer, for example here. Note that we cannot offer support for problems with MITK due to the usage of this kind of installers. -# Compile Qt yourself. This is shortly described below. To compile Qt on Windows using Visual Studio, follow the steps below: -# Download the Qt sources and unpack them, e.g. to C:/qt-everywhere-opensource-src-4.7.4 -# Open a Visual Studio command prompt. Make sure to use the appropriate command prompt for either a 32 bit or 64 bit build. Note that Visual Studio Express does not come with 64bit compilers out of the box (the Professional version does). -# Configure Qt by executing the configure.exe command in your Qt source directory. The following configure options will build a Qt compatible with MITK: \verbatim configure.exe -prefix C:\Qt\4.7.4_vc9_x64 -debug-and-release -qt-sql-sqlite -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -mp -nomake examples -nomake demos -nomake docs \endverbatim -# Build and install the Qt libraries \verbatim nmake nmake install \endverbatim After "nmake install" completed successfully, you may delete your Qt source directory. \section BuildInstructions_Get_Source Get a source tree Since MITK is under active development we recommend to use git to get the most recent version. To make sure you get a stable tree, check the MITK dashboard before checking out. If the build tree is not clean, you can specify an older revision for the checkout or get a stable tar ball from www.mitk.org. If you don't want to use Git, you may also download the current source code (or any other older version) as a tar.gz package by clicking on the snapshot link. You can then skip the clone step below. To clone MITK's current git repository do: \code git clone http://git.mitk.org/MITK.git \endcode \section BuildInstructions_Build_With_CMake Build MITK with CMake Create a new directory for the superbuild binary tree, change to it and call CMake: In the shell (assuming you current directory is the same as the one where you issued the git clone command): \code mkdir MITK-superbuild cd MITK-superbuild ccmake ../MITK \endcode If you use Windows, then you just start the CMake GUI and enter the location of the source and of the binary tree, choose a suitable generator and configure the project. CMake will present you a couple of options, these are the most important ones: - MITK_USE_BLUEBERRY Build the BlueBerry application framework - MITK_USE_Boost Build MITK code which depends on Boost (this will download Boost 1.45.0) - MITK_USE_Boost_LIBRARIES If you need binary Boost libraries, specify them here. - MITK_USE_OpenCV Build MITK code which depends on OpenCV (this will download and build OpenCV 2.3) - MITK_USE_Python Enables Python wrapping in MITK. This will also configure ITK, VTK, and OpenCV (if enabled) to build Python wrappers. - MITK_USE_QT Build MITK code which depends on Qt - QT_QMAKE_EXECUTABLE The path to the qmake executable of your Qt installation If you are satisfied with the configuration of your MITK superbuild, generate the project files with CMake by pressing "Generate". Linux users usually just enter "make" (optionally supplying the number threads to be used for a parallel build): \code make -j4 \endcode Windows users using Visual Studio can open the generated MITK-superbuild.sln solution file in the MITK-superbuild directory and start the build by building the BUILD_ALL project. \section BuildInstructions_Customize Customize your MITK superbuild The MITK superbuild configured MITK with all needed external libraries. The build directories of these libraries, and of MITK itself are located inside the MITK-superbuild directory. For example, the directory layout may look like: \code MITK-superbuild |- ITK-build |- VTK-build |- MITK-build \endcode To change the configuration of the MITK build, choose the MITK-build directory as the binary directory in the CMake GUI. After generating the project files, build the MITK project by either issuing "make" in the MITK-build directory (Linux), or by opening MITK-build/MITK.sln and building the project with Visual Studio. You may also change the configuration of any project configured via the superbuild process. Make sure to also build the changed project and also the projects which depend on it. \section BuildInstructions_Running Running Applications On Linux, just execute the application you want to run. MITK executables are located in MITK-superbuild/MITK-build/bin On Windows, the PATH environment variable must contain the directories containging third-party libraries. The MITK build system generated Windows Batch files in the MITK-build directory which set up a correct environment and opens the appropriate Visual Studio solution file. Use (and maybe modify/enhance) these Batch files to be able to start and debug MITK applications from inside Visual Studio. \section BuildInstructions_Documentation Documentation If you have the Doxygen documentation tool installed, you get a new project (Visual Studio) or "make" target named "doc". You can build this to generate the HTML documentation of MITK in the Documentation/Doxygen directory of your MITK-build binary tree or in the MITK_DOXYGEN_OUTPUT_DIR CMake variable (if specified). \section BuildInstructions_Extending Extend MITK on your own (using the application framework BlueBerry) -\ref NewPluginPage +Please see \ref NewPluginPage \section BuildInstructions_As_Toolkit Use MITK in your own project (as a toolkit) -In the MITK-build binary tree the MITKConfig.cmake file is generated. You can include it in your own project with +To use MITK in your external project, add the CMake command find_package(MITK REQUIRED) +to your CMakeLists.txt and make use of the CMake macros MITK_CHECK_MODULE(result_var ) + and MITK_USE_MODULE() provided by MITK. -find_package(MITK) - -On Windows you also need -find_package(ITK) -find_package(VTK) -to get the library dependencies right. - -After that you can set your include path with - -include_directories(${QMITK_INCLUDE_DIRS}) - -and create an application: - -link_directories(${MITK_LINK_DIRECTORIES}) -add_executable(MyApp MyApp.cpp) -target_link_libraries(Step1 ${QMITK_LIBRARIES}) - -\note IMPORTANT: do not include the ITK_USE_FILE in your project when using MITK. There's a conflict in the ITK - and MITK tree classes which will be resolved soon. +Here is an example CMakeLists.txt (from the Examples/QtAppExample/ directory) which allows you +to create a Qt based application using MITK to display an image. +\include QtAppExample/CMakeLists.txt \section BuildInstructions_Advanced_Customization Superbuild Customization You can inject pre-build third-party libraries into the MITK superbuild by setting certain CMake variables before the first configure step. MITK will then use these third-party libraries instead of downloading and building them itself. Note you must take care to configure those libraries with all options MITK requires. The variables listed below are provided for injecting third-party libraries. Their occurrence in the CMake GUI or in ccmake may depend on specific MITK_USE_* options set to ON. You may also use the variable names below without the EXTERNAL_ prefix, for example when providing their values on a command line call to CMake. - EXTERNAL_BOOST_ROOT Set this variable to your custom Boost installation - EXTERNAL_CTK_DIR Set this variable to your CTK binary tree (the directory containing the CTKConfig.cmake file) - EXTERNAL_CableSwig_DIR Set this variable to your CableSwig binary tree for Python wrapping (the directory containing the CableSwigConfig.cmake file) - EXTERNAL_DCMTK_DIR Set this variable to your DCMTK binary tree (the directory containing the DCMTKConfig.cmake file) - EXTERNAL_GDCM_DIR Set this variable to your GDCM binary tree (the directory containing the GDCMConfig.cmake file) - EXTERNAL_ITK_DIR Set this variable to your ITK binary tree (the directory containing the ITKConfig.cmake file) - EXTERNAL_OpenCV_DIR Set this variable to your OpenCV binary tree (the directory containing the OpenCVConfig.cmake file) - EXTERNAL_VTK_DIR Set this variable to your VTK binary tree (the directory containing the VTKConfig.cmake file) To set CMake options before the first configure step is invoked, supply them on the command line, i.e. \code ccmake -DITK_DIR:PATH=/opt/ITK-release ../MITK \endcode See the following link for more information about how to configure third-party libraries: \subpage BuildToolkits "How to build ITK, VTK and QT" */ diff --git a/Documentation/doxygen.conf.in b/Documentation/doxygen.conf.in index 015b04ad28..6c7dbfa00d 100644 --- a/Documentation/doxygen.conf.in +++ b/Documentation/doxygen.conf.in @@ -1,1899 +1,1900 @@ # Doxyfile 1.8.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = MITK # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @MITK_VERSION_STRING@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Medical Imaging Interaction Toolkit" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @MITK_DOXYGEN_OUTPUT_DIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = "FIXME=\par Fix Me's:\n" \ "BlueBerry=\if BLUEBERRY" \ "endBlueBerry=\endif" \ "bundlemainpage{1}=\page \1" \ "embmainpage{1}=\page \1" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or # internal scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = @MITK_DOXYGEN_INTERNAL_DOCS@ # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = @MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS@ # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = @MITK_DOXYGEN_INTERNAL_DOCS@ # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = YES # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = @MITK_DOXYGEN_GENERATE_TODOLIST@ # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = @MITK_DOXYGEN_GENERATE_BUGLIST@ # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= @MITK_DOXYGEN_GENERATE_DEPRECATEDLIST@ # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = @MITK_DOXYGEN_ENABLED_SECTIONS@ # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 0 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @MITK_SOURCE_DIR@ \ @MITK_BINARY_DIR@ \ @MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.h \ *.cpp \ *.dox \ *.md \ *.txx \ *.tpp \ *.cxx \ *.cmake # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = @MITK_SOURCE_DIR@/Utilities/ann/ \ @MITK_SOURCE_DIR@/Utilities/glew/ \ @MITK_SOURCE_DIR@/Utilities/ipFunc/ \ @MITK_SOURCE_DIR@/Utilities/ipSegmentation/ \ @MITK_SOURCE_DIR@/Utilities/KWStyle/ \ @MITK_SOURCE_DIR@/Utilities/pic2vtk/ \ @MITK_SOURCE_DIR@/Utilities/Poco/ \ @MITK_SOURCE_DIR@/Utilities/qtsingleapplication/ \ @MITK_SOURCE_DIR@/Utilities/qwt/ \ @MITK_SOURCE_DIR@/Utilities/qxt/ \ @MITK_SOURCE_DIR@/Utilities/tinyxml/ \ @MITK_SOURCE_DIR@/Utilities/vecmath/ \ @MITK_SOURCE_DIR@/Applications/PluginGenerator/ \ @MITK_SOURCE_DIR@/BlueBerry/ \ @MITK_SOURCE_DIR@/Deprecated/ \ @MITK_SOURCE_DIR@/Build/ \ @MITK_SOURCE_DIR@/CMake/PackageDepends \ @MITK_SOURCE_DIR@/CMake/QBundleTemplate \ @MITK_SOURCE_DIR@/CMakeExternals \ @MITK_SOURCE_DIR@/Modules/QmitkExt/vtkQtChartHeaders/ \ @MITK_BINARY_DIR@/PT/ \ @MITK_BINARY_DIR@/GP/ \ @MITK_DOXYGEN_ADDITIONAL_EXCLUDE_DIRS@ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = moc_* \ Register* \ */files.cmake \ */.git/* \ */Snippets/* \ */snippets/* \ */testing/* \ */Testing/* \ @MITK_BINARY_DIR@/*.cmake \ @MITK_DOXYGEN_EXCLUDE_PATTERNS@ # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = @MITK_SOURCE_DIR@/Examples/Tutorial/ \ +EXAMPLE_PATH = @MITK_SOURCE_DIR@/Examples/ \ + @MITK_SOURCE_DIR@/Examples/Tutorial/ \ @MITK_SOURCE_DIR@/Examples/QtFreeRender/ \ @MITK_SOURCE_DIR@/Core/Code/ \ @MITK_DOXYGEN_OUTPUT_DIR@/html/extension-points/html/ \ @MITK_SOURCE_DIR@/Documentation/Snippets/ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = @MITK_SOURCE_DIR@/Documentation/Doxygen/ \ @MITK_SOURCE_DIR@/Documentation/Doxygen/Modules/ \ @MITK_SOURCE_DIR@/Documentation/Doxygen/Tutorial/ \ @MITK_SOURCE_DIR@ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@ # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 3 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = @MITK_DOXYGEN_STYLESHEET@ # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = @MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS@ # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = @MITK_DOXYGEN_GENERATE_QHP@ # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = @MITK_DOXYGEN_QCH_FILE@ # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = "org.mitk" # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = MITK # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = @QT_HELPGENERATOR_EXECUTABLE@ # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 300 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = amssymb # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = itkNotUsed(x)= \ "itkSetMacro(name,type)= virtual void Set##name (type _arg);" \ "itkGetMacro(name,type)= virtual type Get##name ();" \ "itkGetConstMacro(name,type)= virtual type Get##name () const;" \ "itkSetStringMacro(name)= virtual void Set##name (const char* _arg);" \ "itkGetStringMacro(name)= virtual const char* Get##name () const;" \ "itkSetClampMacro(name,type,min,max)= virtual void Set##name (type _arg);" \ "itkSetObjectMacro(name,type)= virtual void Set##name (type* _arg);" \ "itkGetObjectMacro(name,type)= virtual type* Get##name ();" \ "itkSetConstObjectMacro(name,type)= virtual void Set##name ( const type* _arg);" \ "itkGetConstObjectMacro(name,type)= virtual const type* Get##name ();" \ "itkGetConstReferenceMacro(name,type)= virtual const type& Get##name ();" \ "itkGetConstReferenceObjectMacro(name,type)= virtual const type::Pointer& Get##name () const;" \ "itkBooleanMacro(name)= virtual void name##On (); virtual void name##Off ();" \ "itkSetVector2Macro(name,type)= virtual void Set##name (type _arg1, type _arg2) virtual void Set##name (type _arg[2]);" \ "itkGetVector2Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2) const; virtual void Get##name (type _arg[2]) const;" \ "itkSetVector3Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3) virtual void Set##name (type _arg[3]);" \ "itkGetVector3Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3) const; virtual void Get##name (type _arg[3]) const;" \ "itkSetVector4Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4) virtual void Set##name (type _arg[4]);" \ "itkGetVector4Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4) const; virtual void Get##name (type _arg[4]) const;" \ "itkSetVector6Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6) virtual void Set##name (type _arg[6]);" \ "itkGetVector6Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4, type& _arg5, type& _arg6) const; virtual void Get##name (type _arg[6]) const;" \ "itkSetVectorMacro(name,type,count)= virtual void Set##name(type data[]);" \ "itkGetVectorMacro(name,type,count)= virtual type* Get##name () const;" \ "itkNewMacro(type)= static Pointer New();" \ "itkTypeMacro(thisClass,superclass)= virtual const char *GetClassName() const;" \ "itkConceptMacro(name,concept)= enum { name = 0 };" \ "ITK_NUMERIC_LIMITS= std::numeric_limits" \ "ITK_TYPENAME= typename" \ "FEM_ABSTRACT_CLASS(thisClass,parentClass)= public: /** Standard Self typedef.*/ typedef thisClass Self; /** Standard Superclass typedef. */ typedef parentClass Superclass; /** Pointer or SmartPointer to an object. */ typedef Self* Pointer; /** Const pointer or SmartPointer to an object. */ typedef const Self* ConstPointer; private:" \ "FEM_CLASS(thisClass,parentClass)= FEM_ABSTRACT_CLASS(thisClass,parentClass) public: /** Create a new object from the existing one */ virtual Baseclass::Pointer Clone() const; /** Class ID for FEM object factory */ static const int CLID; /** Virtual function to access the class ID */ virtual int ClassID() const { return CLID; } /** Object creation in an itk compatible way */ static Self::Pointer New() { return new Self(); } private:" \ FREEVERSION \ ERROR_CHECKING \ HAS_TIFF \ HAS_JPEG \ HAS_NETLIB \ HAS_PNG \ HAS_ZLIB \ HAS_GLUT \ HAS_QT \ VCL_USE_NATIVE_STL=1 \ VCL_USE_NATIVE_COMPLEX=1 \ VCL_HAS_BOOL=1 \ VXL_BIG_ENDIAN=1 \ VXL_LITTLE_ENDIAN=0 \ VNL_DLL_DATA= \ size_t=vcl_size_t \ DOXYGEN_SKIP # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = @BLUEBERRY_DOXYGEN_TAGFILE@ # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = @MITK_DOXYGEN_TAGFILE_NAME@ # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = NO # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = @HAVE_DOT@ # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = @MITK_DOXYGEN_DOT_NUM_THREADS@ # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = @MITK_DOXYGEN_UML_LOOK@ # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = NO # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = NO # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = @DOXYGEN_DOT_PATH@ # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index ad466437ab..22758f2ce2 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,64 +1,65 @@ set(MITK_DEFAULT_SUBPROJECTS MITK-Examples) #----------------------------------------------------------------------------- # Set-up example plugins #----------------------------------------------------------------------------- if(MITK_USE_BLUEBERRY) # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_example_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk OUTPUT_VARIABLE ${varname}) endmacro() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Plugins/${mitk_example_plugin}) endforeach() ctkMacroSetupPlugins(${mitk_example_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ COMPACT_OPTIONS) set(MITK_EXAMPLE_PLUGIN_TARGETS ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) ctkFunctionExtractOptionNameAndValue(${mitk_example_plugin} plugin_name plugin_value) string(REPLACE "." "_" _plugin_target ${plugin_name}) list(APPEND MITK_EXAMPLE_PLUGIN_TARGETS ${_plugin_target}) mark_as_advanced(${${_plugin_target}_option_name}) endforeach() endif() #----------------------------------------------------------------------------- # Add example executables #----------------------------------------------------------------------------- set(MITK_DIR ${PROJECT_BINARY_DIR}) set(MITK_EXPORTS_FILE_INCLUDED 1) set(_example_dirs MbiLog QtFreeRender ) if(MITK_USE_QT) list(APPEND _example_dirs Tutorial + QtAppExample ) endif() if(MITK_USE_BLUEBERRY) list(APPEND _example_dirs AppFramework ) endif() foreach(_example_dir ${_example_dirs}) add_subdirectory(${_example_dir}) endforeach() diff --git a/Examples/MbiLog/MitkLogExample.cpp b/Examples/MbiLog/MitkLogExample.cpp index f7a2d44b3d..08f4887254 100644 --- a/Examples/MbiLog/MitkLogExample.cpp +++ b/Examples/MbiLog/MitkLogExample.cpp @@ -1,9 +1,24 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include int main(int /*argc*/, char** /*argv*/) { MITK_INFO << "Test log ..." ; return EXIT_SUCCESS; } diff --git a/Examples/QtAppExample/CMakeLists.txt b/Examples/QtAppExample/CMakeLists.txt new file mode 100644 index 0000000000..5105f5ea17 --- /dev/null +++ b/Examples/QtAppExample/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 2.8.4) + +project(QtAppExample) + +find_package(MITK REQUIRED) + +# Check that MITK has been build with Qt support +if(NOT MITK_USE_QT) + message(SEND_ERROR "MITK needs to be built with MITK_USE_QT set to ON") +endif() + +# Check prerequisites for this application. +# We need the Qmitk module. +MITK_CHECK_MODULE(result Qmitk) +if(result) + message(SEND_ERROR "MITK module(s) \"${result}\" not available from the MITK build at ${MITK_DIR}") +endif() + +# Set-up the build system to use the Qmitk module +MITK_USE_MODULE(Qmitk) +include_directories(${ALL_INCLUDE_DIRECTORIES}) +link_directories(${ALL_LIBRARY_DIRS}) + +add_executable(${PROJECT_NAME} Step1.cpp) +target_link_libraries(${PROJECT_NAME} ${ALL_LIBRARIES}) + + +# This is for subproject support inside the MITK source tree. +# Ignore/remove the following code if you build an external application. +set_property(TARGET ${PROJECT_NAME} PROPERTY LABELS ${MITK_DEFAULT_SUBPROJECTS}) +foreach(subproject ${MITK_DEFAULT_SUBPROJECTS}) + add_dependencies(${subproject} ${PROJECT_NAME}) +endforeach() + diff --git a/Examples/Tutorial/Step1.cpp b/Examples/QtAppExample/Step1.cpp similarity index 93% copy from Examples/Tutorial/Step1.cpp copy to Examples/QtAppExample/Step1.cpp index 55482c0e1c..c24b4f6437 100644 --- a/Examples/Tutorial/Step1.cpp +++ b/Examples/QtAppExample/Step1.cpp @@ -1,115 +1,107 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include #include #include #include -//##Documentation -//## @brief Load image (pic format) and display it in a 2D view +// Load image (nrrd format) and display it in a 2D view int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if (argc < 2) { fprintf( stderr, "Usage: %s [filename] \n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage // The DataStorage manages all data objects. It is used by the // rendering mechanism to render all data objects // We use the standard implementation mitk::StandaloneDataStorage. mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading a file //************************************************************************* // Create a DataNodeFactory to read a data format supported // by the DataNodeFactory (many image formats, surface formats, etc.) mitk::DataNodeFactory::Pointer reader=mitk::DataNodeFactory::New(); const char * filename = argv[1]; try { reader->SetFileName(filename); reader->Update(); //************************************************************************* // Part III: Put the data into the datastorage //************************************************************************* // Add the node to the DataStorage ds->Add(reader->GetOutput()); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); exit(2); } //************************************************************************* // Part IV: Create window and pass the datastorage to it //************************************************************************* // Create a RenderWindow QmitkRenderWindow renderWindow; // Tell the RenderWindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(ds); // Initialize the RenderWindow mitk::TimeSlicedGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); //mitk::RenderingManager::GetInstance()->InitializeViews(); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos( 0 ); //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize( 256, 256 ); - - // for testing - #include "QtTesting.h" - if (strcmp(argv[argc-1], "-testing") != 0) - return qtapplication.exec(); - else - return QtTesting(); + + qtapplication.exec(); // cleanup: Remove References to DataStorage. This will delete the object ds = NULL; } -/** -\example Step1.cpp -*/ + diff --git a/Examples/Tutorial/Step1.cpp b/Examples/Tutorial/Step1.cpp index 55482c0e1c..f60d58d6f0 100644 --- a/Examples/Tutorial/Step1.cpp +++ b/Examples/Tutorial/Step1.cpp @@ -1,115 +1,115 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include #include #include #include //##Documentation -//## @brief Load image (pic format) and display it in a 2D view +//## @brief Load image (nrrd format) and display it in a 2D view int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if (argc < 2) { fprintf( stderr, "Usage: %s [filename] \n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage // The DataStorage manages all data objects. It is used by the // rendering mechanism to render all data objects // We use the standard implementation mitk::StandaloneDataStorage. mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading a file //************************************************************************* // Create a DataNodeFactory to read a data format supported // by the DataNodeFactory (many image formats, surface formats, etc.) mitk::DataNodeFactory::Pointer reader=mitk::DataNodeFactory::New(); const char * filename = argv[1]; try { reader->SetFileName(filename); reader->Update(); //************************************************************************* // Part III: Put the data into the datastorage //************************************************************************* // Add the node to the DataStorage ds->Add(reader->GetOutput()); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); exit(2); } //************************************************************************* // Part IV: Create window and pass the datastorage to it //************************************************************************* // Create a RenderWindow QmitkRenderWindow renderWindow; // Tell the RenderWindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(ds); // Initialize the RenderWindow mitk::TimeSlicedGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); //mitk::RenderingManager::GetInstance()->InitializeViews(); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos( 0 ); //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize( 256, 256 ); // for testing #include "QtTesting.h" if (strcmp(argv[argc-1], "-testing") != 0) return qtapplication.exec(); else return QtTesting(); // cleanup: Remove References to DataStorage. This will delete the object ds = NULL; } /** \example Step1.cpp */ diff --git a/Examples/Tutorial/Step2.cpp b/Examples/Tutorial/Step2.cpp index 62806692b4..df3c30a0a9 100644 --- a/Examples/Tutorial/Step2.cpp +++ b/Examples/Tutorial/Step2.cpp @@ -1,121 +1,118 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include #include #include #include //##Documentation //## @brief Load one or more data sets (many image, surface //## and other formats) and display it in a 2D view -//## -//## Only very slightly different to Step1: Use DataNodeFactory -//## instead of PicFileReader, and read more than one data set. int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if(argc<2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a data storage object. We will use it as a singleton mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for(i=1; iSetFileName(filename); nodeReader->Update(); //********************************************************************* // Part III: Put the data into the datastorage //********************************************************************* // Since the DataNodeFactory directly creates a node, // use the datastorage to add the read node storage->Add(nodeReader->GetOutput()); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); exit(2); } } //************************************************************************* // Part IV: Create window and pass the datastorage to it //************************************************************************* // Create a RenderWindow QmitkRenderWindow renderWindow; // Tell the RenderWindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(storage); // Initialize the RenderWindow mitk::TimeSlicedGeometry::Pointer geo = storage->ComputeBoundingGeometry3D(storage->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos( 2 ); //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize( 256, 256 ); // for testing #include "QtTesting.h" if(strcmp(argv[argc-1], "-testing")!=0) return qtapplication.exec(); else return QtTesting(); } /** \example Step2.cpp */ diff --git a/Examples/Tutorial/Step6RegionGrowing.txx b/Examples/Tutorial/Step6RegionGrowing.txx index ba0c5d8a7f..28ccffdb67 100644 --- a/Examples/Tutorial/Step6RegionGrowing.txx +++ b/Examples/Tutorial/Step6RegionGrowing.txx @@ -1,78 +1,93 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "Step6.h" #include #include #include #include #include #include template < typename TPixel, unsigned int VImageDimension > void RegionGrowing( itk::Image* itkImage, Step6* step6 ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef float InternalPixelType; typedef itk::Image< InternalPixelType, VImageDimension > InternalImageType; mitk::Geometry3D* geometry = step6->m_FirstImage->GetGeometry(); // create itk::CurvatureFlowImageFilter for smoothing and set itkImage as input typedef itk::CurvatureFlowImageFilter< ImageType, InternalImageType > CurvatureFlowFilter; typename CurvatureFlowFilter::Pointer smoothingFilter = CurvatureFlowFilter::New(); smoothingFilter->SetInput( itkImage ); smoothingFilter->SetNumberOfIterations( 4 ); smoothingFilter->SetTimeStep( 0.0625 ); // create itk::ConnectedThresholdImageFilter and set filtered image as input typedef itk::ConnectedThresholdImageFilter< InternalImageType, ImageType > RegionGrowingFilterType; typedef typename RegionGrowingFilterType::IndexType IndexType; typename RegionGrowingFilterType::Pointer regGrowFilter = RegionGrowingFilterType::New(); regGrowFilter->SetInput( smoothingFilter->GetOutput() ); regGrowFilter->SetLower( step6->GetThresholdMin() ); regGrowFilter->SetUpper( step6->GetThresholdMax() ); // convert the points in the PointSet m_Seeds (in world-coordinates) to // "index" values, i.e. points in pixel coordinates, and add these as seeds // to the RegionGrower mitk::PointSet::PointsConstIterator pit, pend = step6->m_Seeds->GetPointSet()->GetPoints()->End(); IndexType seedIndex; for (pit = step6->m_Seeds->GetPointSet()->GetPoints()->Begin(); pit != pend; ++pit) { geometry->WorldToIndex(pit.Value(), seedIndex); regGrowFilter->AddSeed( seedIndex ); } regGrowFilter->GetOutput()->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitk::CastToMitkImage(regGrowFilter->GetOutput(), mitkImage); if (step6->m_ResultNode.IsNull()) { step6->m_ResultNode = mitk::DataNode::New(); step6->m_DataStorage->Add(step6->m_ResultNode); } step6->m_ResultNode->SetData(mitkImage); // set some additional properties step6->m_ResultNode->SetProperty("name", mitk::StringProperty::New("segmentation")); step6->m_ResultNode->SetProperty("binary", mitk::BoolProperty::New(true)); step6->m_ResultNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); step6->m_ResultNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); step6->m_ResultNode->SetProperty("layer", mitk::IntProperty::New(1)); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetAuto( mitkImage ); levWinProp->SetLevelWindow( levelwindow ); step6->m_ResultNode->SetProperty( "levelwindow", levWinProp ); step6->m_ResultImage = static_cast(step6->m_ResultNode->GetData()); } /** \example Step6RegionGrowing.txx */ diff --git a/Examples/Tutorial/mitkWithITKAndVTK.cpp b/Examples/Tutorial/mitkWithITKAndVTK.cpp index 90767280d6..66c81934fb 100644 --- a/Examples/Tutorial/mitkWithITKAndVTK.cpp +++ b/Examples/Tutorial/mitkWithITKAndVTK.cpp @@ -1,67 +1,82 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include #include #include #include #include #include #include #include /// /// Small application for demonstrating the interaction between MITK, /// ITK and VTK (not necessarily useful). /// int main( int /*argc*/, char ** argv ) { // MITK: Read a .pic.gz file, e.g. Core/Code/Testing/Data/Pic3D.pic.gz from // disk mitk::PicFileReader::Pointer reader = mitk::PicFileReader::New(); const char * filename = argv[1]; try { reader->SetFileName(filename); reader->Update(); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); return EXIT_FAILURE; } mitk::Image::Pointer mitkImage = reader->GetOutput(); // ITK: Image smoothing // Create ITK image, cast from MITK image typedef itk::Image< short , 3 > ImageType; ImageType::Pointer itkImage = ImageType::New(); mitk::CastToItkImage( mitkImage, itkImage ); typedef itk::DiscreteGaussianImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkImage ); filter->SetVariance( 2 ); filter->SetMaximumKernelWidth( 5 ); filter->Update(); // run filter // reimport filtered image data mitk::CastToMitkImage( filter->GetOutput(), mitkImage ); // VTK: Show result in renderwindow vtkImageViewer *viewer=vtkImageViewer::New(); vtkRenderWindowInteractor* renderWindowInteractor =vtkRenderWindowInteractor ::New(); viewer->SetupInteractor(renderWindowInteractor); viewer->SetInput(mitkImage->GetVtkImageData()); viewer->Render(); viewer->SetColorWindow(255); viewer->SetColorLevel(128); renderWindowInteractor->Start(); renderWindowInteractor->Delete(); viewer->Delete(); return EXIT_SUCCESS; } diff --git a/Modules/CameraCalibration/mitkAlgorithm.h b/Modules/CameraCalibration/mitkAlgorithm.h index 3724c1cfbf..096afe3bb0 100644 --- a/Modules/CameraCalibration/mitkAlgorithm.h +++ b/Modules/CameraCalibration/mitkAlgorithm.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkAlgorithm_h #define mitkAlgorithm_h namespace mitk { /// /// filter "Algorithm" interface = a class which does /// its work when calling this function /// this is a general polling mechansim /// class Algorithm { public: /// /// do update steps here /// virtual void Update() = 0; }; } // namespace mitk #endif // mitkAlgorithm_h diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.cpp b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp index 38d0bf4b55..f997ea047b 100644 --- a/Modules/CameraCalibration/mitkCameraIntrinsics.cpp +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp @@ -1,485 +1,500 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkCameraIntrinsics.h" #include #include #include mitk::CameraIntrinsics::CameraIntrinsics() : m_Valid(false), m_Mutex(itk::FastMutexLock::New()) { m_CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); m_CameraMatrix.at(2,2) = 1.0; m_DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); } mitk::CameraIntrinsics::~CameraIntrinsics() { } bool mitk::CameraIntrinsics::Equals( const CameraIntrinsics* other ) const { return other->GetDistorsionCoeffsAsPoint4D()== this->GetDistorsionCoeffsAsPoint4D() && other->GetFocalPoint()== this->GetFocalPoint() && other->GetPrincipalPoint() == this->GetPrincipalPoint(); } void mitk::CameraIntrinsics::Copy(const CameraIntrinsics* other) { this->SetIntrinsics( other->GetCameraMatrix().clone() , other->GetDistorsionCoeffs().clone() ); } bool mitk::CameraIntrinsics::IsValid() const { itk::MutexLockHolder lock(*m_Mutex); return m_Valid; } mitk::CameraIntrinsics::Pointer mitk::CameraIntrinsics::Clone() const { mitk::CameraIntrinsics::Pointer copy = mitk::CameraIntrinsics::New(); copy->SetIntrinsics( this->GetCameraMatrix(), this->GetDistorsionCoeffs() ); return copy; } vnl_matrix_fixed mitk::CameraIntrinsics::GetVnlCameraMatrix() const { vnl_matrix_fixed mat; mat.set_identity(); { itk::MutexLockHolder lock(*m_Mutex); mat(0,0) = m_CameraMatrix.at(0,0); mat(1,1) = m_CameraMatrix.at(1,1); mat(0,2) = m_CameraMatrix.at(0,2); mat(1,2) = m_CameraMatrix.at(1,2); } return mat; } void mitk::CameraIntrinsics::SetCameraMatrix( const vnl_matrix_fixed& _CameraMatrix ) { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = _CameraMatrix(0,0); m_CameraMatrix.at(1,1) = _CameraMatrix(1,1); m_CameraMatrix.at(0,2) = _CameraMatrix(0,2); m_CameraMatrix.at(1,2) = _CameraMatrix(1,2); } vnl_matrix_fixed mitk::CameraIntrinsics::GetVnlCameraMatrix3x4() const { vnl_matrix_fixed mat; mat.fill(0); mat.update( this->GetVnlCameraMatrix().as_matrix() ); return mat; } void mitk::CameraIntrinsics::SetIntrinsics( const cv::Mat& _CameraMatrix , const cv::Mat& _DistorsionCoeffs) { { itk::MutexLockHolder lock(*m_Mutex); if( _CameraMatrix.cols != 3 || _CameraMatrix.rows != 3) throw std::invalid_argument("Wrong format of camera matrix. Should be 3x3" " double."); endoAssertMsg( (_DistorsionCoeffs.cols == 5) && _DistorsionCoeffs.rows == 1, "Wrong format of distorsion coefficients" " vector. Should be 5x1 double."); m_CameraMatrix = _CameraMatrix.clone(); m_DistorsionCoeffs = _DistorsionCoeffs.clone(); m_Valid = true; } this->Modified(); } void mitk::CameraIntrinsics::SetIntrinsics( const mitk::Point3D& focalPoint, const mitk::Point3D& principalPoint, const mitk::Point4D& distortionCoefficients) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = focalPoint[0]; m_CameraMatrix.at(1,1) = focalPoint[1]; m_CameraMatrix.at(0,2) = principalPoint[0]; m_CameraMatrix.at(1,2) = principalPoint[1]; m_DistorsionCoeffs.at(0,0) = distortionCoefficients[0]; m_DistorsionCoeffs.at(0,1) = distortionCoefficients[1]; m_DistorsionCoeffs.at(0,2) = distortionCoefficients[2]; m_DistorsionCoeffs.at(0,3) = distortionCoefficients[3]; } this->Modified(); } void mitk::CameraIntrinsics::SetFocalLength( double x, double y ) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = x; m_CameraMatrix.at(1,1) = y; } this->Modified(); } void mitk::CameraIntrinsics::SetPrincipalPoint( double x, double y ) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,2) = x; m_CameraMatrix.at(1,2) = y; } this->Modified(); } void mitk::CameraIntrinsics::SetDistorsionCoeffs( double k1, double k2, double p1, double p2 ) { { itk::MutexLockHolder lock(*m_Mutex); m_DistorsionCoeffs.at(0,0) = k1; m_DistorsionCoeffs.at(0,1) = k2; m_DistorsionCoeffs.at(0,2) = p1; m_DistorsionCoeffs.at(0,3) = p2; } this->Modified(); } cv::Mat mitk::CameraIntrinsics::GetCameraMatrix() const { itk::MutexLockHolder lock(*m_Mutex); return m_CameraMatrix.clone(); // return a copy of this small matrix } cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() const { itk::MutexLockHolder lock(*m_Mutex); return m_DistorsionCoeffs.clone(); // return a copy of this small matrix } cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() { const CameraIntrinsics* intrinsics = this; return intrinsics->GetDistorsionCoeffs(); } std::string mitk::CameraIntrinsics::ToString() const { itk::MutexLockHolder lock(*m_Mutex); std::ostringstream s; s.precision(12); const cv::Mat& CameraMatrix = m_CameraMatrix; const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; s.str(""); s << this->GetNameOfClass() << ": "; s << "fx = " << CameraMatrix.at(0,0); s << ", fy = " << CameraMatrix.at(1,1); s << ", cx = " << CameraMatrix.at(0,2); s << ", cy = " << CameraMatrix.at(1,2); s << ", k1 = " << DistorsionCoeffs.at(0,0); s << ", k2 = " << DistorsionCoeffs.at(0,1); s << ", p1 = " << DistorsionCoeffs.at(0,2); s << ", p2 = " << DistorsionCoeffs.at(0,3); //s << ", k3 = " << DistorsionCoeffs.at(0,4); return s.str(); } void mitk::CameraIntrinsics::ToXML(TiXmlElement* elem) const { itk::MutexLockHolder lock(*m_Mutex); elem->SetValue(this->GetNameOfClass()); std::ostringstream s; s.precision(12); const cv::Mat& CameraMatrix = m_CameraMatrix; s.str(""); s << CameraMatrix.at(0,0); elem->SetAttribute( "fx", s.str() ); s.str(""); s << CameraMatrix.at(1,1); elem->SetAttribute( "fy", s.str() ); s.str(""); s << CameraMatrix.at(0,2); elem->SetAttribute( "cx", s.str() ); s.str(""); s << CameraMatrix.at(1,2); elem->SetAttribute( "cy", s.str() ); const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; s.str(""); s << DistorsionCoeffs.at(0,0); elem->SetAttribute( "k1", s.str() ); s.str(""); s << DistorsionCoeffs.at(0,1); elem->SetAttribute( "k2", s.str() ); s.str(""); s << DistorsionCoeffs.at(0,2); elem->SetAttribute( "p1", s.str() ); s.str(""); s << DistorsionCoeffs.at(0,3); elem->SetAttribute( "p2", s.str() ); elem->SetAttribute("Valid", m_Valid); //s.str(""); s << DistorsionCoeffs.at(4,0); //elem->SetAttribute( "k3", s.str() ); } void mitk::CameraIntrinsics::FromGMLCalibrationXML(TiXmlElement* elem) { assert( elem ); assert( elem->ValueStr() == "results" ); cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); CameraMatrix.at(2,2) = 1.0; cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); TiXmlElement* focus_lenXElem = elem->FirstChildElement("focus_lenX"); endoAssert( focus_lenXElem != 0 ); CameraMatrix.at(0,0) = atof( focus_lenXElem->GetText() ); TiXmlElement* focus_lenYElem = elem->FirstChildElement("focus_lenY"); endoAssert( focus_lenYElem != 0 ); CameraMatrix.at(1,1) = atof( focus_lenYElem->GetText() ); TiXmlElement* PrincipalXElem = elem->FirstChildElement("PrincipalX"); endoAssert( PrincipalXElem != 0 ); CameraMatrix.at(0,2) = atof( PrincipalXElem->GetText() ); TiXmlElement* PrincipalYElem = elem->FirstChildElement("PrincipalY"); endoAssert( PrincipalYElem != 0 ); CameraMatrix.at(1,2) = atof( PrincipalYElem->GetText() ); // DISTORSION COEFFS TiXmlElement* Dist1Elem = elem->FirstChildElement("Dist1"); endoAssert( Dist1Elem != 0 ); DistorsionCoeffs.at(0,0) = atof( Dist1Elem->GetText() ); TiXmlElement* Dist2Elem = elem->FirstChildElement("Dist2"); endoAssert( Dist2Elem != 0 ); DistorsionCoeffs.at(0,1) = atof( Dist2Elem->GetText() ); TiXmlElement* Dist3Elem = elem->FirstChildElement("Dist3"); endoAssert( Dist3Elem != 0 ); DistorsionCoeffs.at(0,2) = atof( Dist3Elem->GetText() ); TiXmlElement* Dist4Elem = elem->FirstChildElement("Dist4"); endoAssert( Dist4Elem != 0 ); DistorsionCoeffs.at(0,3) = atof( Dist4Elem->GetText() ); int valid = 0; elem->QueryIntAttribute("Valid", &valid); { itk::MutexLockHolder lock(*m_Mutex); m_Valid = static_cast(valid); m_CameraMatrix = CameraMatrix; m_DistorsionCoeffs = DistorsionCoeffs; } this->Modified(); } void mitk::CameraIntrinsics::FromXML(TiXmlElement* elem) { endoAssert ( elem ); MITK_DEBUG << elem->Value(); std::string filename; if(elem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS) { this->FromXMLFile(filename); return; } else if(strcmp(elem->Value(), "CalibrationProject") == 0) { this->FromGMLCalibrationXML(elem->FirstChildElement("results")); return; } assert ( elem ); if(strcmp(elem->Value(), this->GetNameOfClass()) != 0) elem = elem->FirstChildElement(this->GetNameOfClass()); std::ostringstream err; // CAMERA MATRIX cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); CameraMatrix.at(2,2) = 1.0; float val = 0.0f; if(elem->QueryFloatAttribute("fx", &val) == TIXML_SUCCESS) CameraMatrix.at(0,0) = val; else err << "fx, "; if(elem->QueryFloatAttribute("fy", &val) == TIXML_SUCCESS) CameraMatrix.at(1,1) = val; else err << "fy, "; if(elem->QueryFloatAttribute("cx", &val) == TIXML_SUCCESS) CameraMatrix.at(0,2) = val; else err << "cx, "; if(elem->QueryFloatAttribute("cy", &val) == TIXML_SUCCESS) CameraMatrix.at(1,2) = val; else err << "cy, "; // DISTORSION COEFFS endodebug( "creating DistorsionCoeffs from XML file") cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); if(elem->QueryFloatAttribute("k1", &val) == TIXML_SUCCESS) DistorsionCoeffs.at(0,0) = val; else err << "k1, "; if(elem->QueryFloatAttribute("k2", &val) == TIXML_SUCCESS) DistorsionCoeffs.at(0,1) = val; else err << "k2, "; if(elem->QueryFloatAttribute("p1", &val) == TIXML_SUCCESS) DistorsionCoeffs.at(0,2) = val; else err << "p1, "; if(elem->QueryFloatAttribute("p2", &val) == TIXML_SUCCESS) DistorsionCoeffs.at(0,3) = val; else err << "p2, "; DistorsionCoeffs.at(0,4) = 0.0; /*if(elem->QueryFloatAttribute("k3", &val) == TIXML_SUCCESS) DistorsionCoeffs.at(4,0) = val; else err << "k3, ";*/ std::string errorStr = err.str(); int errLength = errorStr.length(); if(errLength > 0) { errorStr = errorStr.substr(0, errLength-2); errorStr.append(" not found"); throw std::invalid_argument(err.str()); } int valid = 0; elem->QueryIntAttribute("Valid", &valid); { itk::MutexLockHolder lock(*m_Mutex); m_Valid = static_cast(valid); m_CameraMatrix = CameraMatrix; m_DistorsionCoeffs = DistorsionCoeffs; } this->Modified(); } double mitk::CameraIntrinsics::GetFocalLengthX() const { itk::MutexLockHolder lock(*m_Mutex); double FocalLengthX = m_CameraMatrix.at(0,0); return FocalLengthX; } double mitk::CameraIntrinsics::GetFocalLengthY() const { itk::MutexLockHolder lock(*m_Mutex); double FocalLengthY = m_CameraMatrix.at(1,1);; return FocalLengthY; } double mitk::CameraIntrinsics::GetPrincipalPointX() const { itk::MutexLockHolder lock(*m_Mutex); double PrincipalPointX = m_CameraMatrix.at(0,2); return PrincipalPointX; } double mitk::CameraIntrinsics::GetPrincipalPointY() const { itk::MutexLockHolder lock(*m_Mutex); double PrincipalPointY = m_CameraMatrix.at(1,2); return PrincipalPointY; } mitk::Point4D mitk::CameraIntrinsics::GetDistorsionCoeffsAsPoint4D() const { itk::MutexLockHolder lock(*m_Mutex); mitk::Point4D coeffs; coeffs[0] = m_DistorsionCoeffs.at(0,0); coeffs[1] = m_DistorsionCoeffs.at(0,1); coeffs[2] = m_DistorsionCoeffs.at(0,2); coeffs[3] = m_DistorsionCoeffs.at(0,3); return coeffs; } mitk::Point3D mitk::CameraIntrinsics::GetFocalPoint() const { mitk::Point3D p; p[0] = this->GetFocalLengthX(); p[1] = this->GetFocalLengthY(); p[2] = 0; return p; } mitk::Point3D mitk::CameraIntrinsics::GetPrincipalPoint() const { mitk::Point3D p; p[0] = this->GetPrincipalPointX(); p[1] = this->GetPrincipalPointY(); p[2] = 0; return p; } vnl_vector_fixed mitk::CameraIntrinsics::GetFocalPointAsVnlVector() const { vnl_vector_fixed vec; vec[0] = this->GetFocalLengthX(); vec[1] = this->GetFocalLengthY(); return vec; } vnl_vector_fixed mitk::CameraIntrinsics::GetPrincipalPointAsVnlVector() const { vnl_vector_fixed vec; vec[0] = this->GetPrincipalPointX(); vec[1] = this->GetPrincipalPointY(); return vec; } std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p) { os << p->ToString(); return os; } std::string mitk::CameraIntrinsics::GetString() { return this->ToString(); } std::string mitk::CameraIntrinsics::ToOctaveString( const std::string& varName) { std::ostringstream s; s << varName << " = [" << this->GetFocalLengthX() << " 0 " << this->GetPrincipalPointX() << "; 0 " << this->GetFocalLengthY() << " " << this->GetPrincipalPointY() << ";" << " 0 0 1 ];"; return s.str(); } void mitk::CameraIntrinsics::SetValid( bool valid ) { itk::MutexLockHolder lock(*m_Mutex); m_Valid = valid; } diff --git a/Modules/CameraCalibration/mitkCvMatCompare.h b/Modules/CameraCalibration/mitkCvMatCompare.h index e6cf602574..9987d89a37 100644 --- a/Modules/CameraCalibration/mitkCvMatCompare.h +++ b/Modules/CameraCalibration/mitkCvMatCompare.h @@ -1,95 +1,110 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkCvMatCompare_h #define mitkCvMatCompare_h #include #include #include #include namespace mitk { /// /// compare two matrices with a given epsilon /// class CvMatCompare: virtual public Algorithm { public: /// /// init default values and save references /// CvMatCompare( const Epsilon* _Epsilon, bool* _Equals): m_CvMat1(0), m_CvMat2(0), m_Epsilon(_Epsilon), m_Equals(_Equals) { } /// /// init default values and save references /// CvMatCompare( const cv::Mat* _CvMat1, const cv::Mat* _CvMat2, const Epsilon* _Epsilon, bool* _Equals): m_CvMat1(_CvMat1), m_CvMat2(_CvMat2), m_Epsilon(_Epsilon), m_Equals(_Equals) { } void SetMatrices( const cv::Mat* _CvMat1, const cv::Mat* _CvMat2 ) { m_CvMat1 = _CvMat1; m_CvMat2 = _CvMat2; } void SetMatrix1( const cv::Mat* _CvMat1 ) { m_CvMat1 = _CvMat1; } void SetMatrix2( const cv::Mat* _CvMat2 ) { m_CvMat2 = _CvMat2; } /// /// executes the Algorithm /// void Update() { assert( m_CvMat1 && m_CvMat2 ); cv::Mat dst; cv::absdiff( (*m_CvMat1), (*m_CvMat2), dst); double max = 0; cv::minMaxLoc( dst, 0, &max ); endodebugvar( max ) (*m_Equals) = max <= *m_Epsilon; } private: /// /// CvMatCompare input member variable /// const cv::Mat* m_CvMat1; /// /// CvMatCompare input member variable /// const cv::Mat* m_CvMat2; /// /// CvMatCompare input member variable /// const Epsilon* m_Epsilon; /// /// CvMatCompare output member variable /// bool* m_Equals; }; } // namespace mitk #endif // mitkCvMatCompare_h diff --git a/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h index c918a142e8..a4d04aca45 100644 --- a/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h +++ b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h @@ -1,73 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkCvMatFromVnlMatrix_h #define mitkCvMatFromVnlMatrix_h #include #include #include #include #include namespace mitk { /// /// casts a random cv::Mat to a vnl Matrix /// if the columns of the first row are > 1 /// then the Matrix is filled with the values from this row /// otherwise the first elements of each row are used /// to fill the Matrix /// template class CvMatFromVnlMatrix: virtual public Algorithm { public: /// /// init default values and save references /// CvMatFromVnlMatrix( const vnl_matrix* _VnlMatrix, cv::Mat* _CvMat): m_VnlMatrix(_VnlMatrix), m_CvMat(_CvMat) { } /// /// templated function for multiplexed cv::Mat /// template static void Cast( const vnl_matrix& vnlMat, cv::Mat& cvMat ) { endodebugvar( vnlMat ) cvMat = cv::Mat(vnlMat.rows(), vnlMat.cols(), cv::DataType::type); for(unsigned int i=0; i(i,j) = static_cast( vnlMat(i,j) ); // endodebugvar( vnlMat(i,j) ) // endodebugvar( cvMat.at(i,j) ) } } } /// /// executes the Algorithm /// void Update() { Cast( *m_VnlMatrix, *m_CvMat ); } private: /// /// CvMatFromVnlMatrix input member variable /// const vnl_matrix* m_VnlMatrix; /// /// CvMatFromVnlMatrix output member variable /// cv::Mat* m_CvMat; }; } // namespace mitk #endif // mitkCvMatFromVnlMatrix_h diff --git a/Modules/CameraCalibration/mitkCvMatFromVnlVector.h b/Modules/CameraCalibration/mitkCvMatFromVnlVector.h index cca34d1739..6b7c95fa71 100644 --- a/Modules/CameraCalibration/mitkCvMatFromVnlVector.h +++ b/Modules/CameraCalibration/mitkCvMatFromVnlVector.h @@ -1,58 +1,73 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkCvMatFromVnlVector_h #define mitkCvMatFromVnlVector_h #include #include #include namespace mitk { /// /// casts a random cv::Mat to a vnl vector /// if the columns of the first row are > 1 /// then the vector is filled with the values from this row /// otherwise the first elements of each row are used /// to fill the vector /// template class CvMatFromVnlVector: virtual public Algorithm { public: /// /// init default values and save references /// CvMatFromVnlVector( const vnl_vector* _VnlVector, cv::Mat* _CvMat): m_CvMatFromVnlMatrix(&m_VnlMatrix, _CvMat), m_VnlVector(_VnlVector) { } /// /// executes the Algorithm /// void Update() { m_VnlMatrix.set_size( m_VnlVector->size(), 1 ); m_VnlMatrix.set_column(0, *m_VnlVector); m_CvMatFromVnlMatrix.Update(); } private: /// /// CvMatFromVnlVector input member variable /// vnl_matrix m_VnlMatrix; /// /// internal algorithm to create a vnl matrix from a random cv mat /// mitk::CvMatFromVnlMatrix m_CvMatFromVnlMatrix; /// /// CvMatFromVnlVector input member variable /// const vnl_vector* m_VnlVector; }; } // namespace mitk #endif // mitkCvMatFromVnlVector_h diff --git a/Modules/CameraCalibration/mitkEndoDebug.cpp b/Modules/CameraCalibration/mitkEndoDebug.cpp index 42720c3523..094c26b807 100644 --- a/Modules/CameraCalibration/mitkEndoDebug.cpp +++ b/Modules/CameraCalibration/mitkEndoDebug.cpp @@ -1,246 +1,261 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkEndoDebug.h" #include #include #include #include #include #include namespace mitk { struct EndoDebugData { EndoDebugData() : m_DebugEnabled(false) , m_ShowImagesInDebug(false) , m_ShowImagesTimeOut(false) , m_Mutex(itk::FastMutexLock::New()) , m_DebugImagesOutputDirectory("") { } std::set m_FilesToDebug; std::set m_SymbolsToDebug; bool m_DebugEnabled; bool m_ShowImagesInDebug; size_t m_ShowImagesTimeOut; std::ofstream m_Stream; itk::FastMutexLock::Pointer m_Mutex; std::string m_DebugImagesOutputDirectory; }; EndoDebug::EndoDebug() : d ( new EndoDebugData ) { } EndoDebug::~EndoDebug() { if(d->m_Stream.is_open()) d->m_Stream.close(); delete d; } EndoDebug& EndoDebug::GetInstance() { static EndoDebug instance; return instance; } std::string EndoDebug::GetUniqueFileName( const std::string& dir, const std::string& ext ) { std::stringstream s; s.precision( 0 ); std::string filename; int i = 0; while( filename.empty() || itksys::SystemTools::FileExists( (dir+"/"+filename).c_str() ) ) { s.str(""); s << i; filename = s.str() + "." + ext; ++i; } filename = dir+"/"+filename; return filename; } std::string EndoDebug::GetFilenameWithoutExtension(const std::string& s) { return itksys::SystemTools::GetFilenameWithoutExtension( s ); } void EndoDebug::AddFileToDebug(const std::string& s) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_FilesToDebug.insert( s ); } } void EndoDebug::AddSymbolToDebug(const std::string& symbolToDebug) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_SymbolsToDebug.insert( symbolToDebug ); } } bool EndoDebug::DebugSymbol(const std::string& s) { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_SymbolsToDebug.find(s) != d->m_SymbolsToDebug.end(); } } bool EndoDebug::DebugFile(const std::string& s) { std::string filename = GetFilenameWithoutExtension(s); { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_FilesToDebug.find(filename) != d->m_FilesToDebug.end(); } } bool EndoDebug::Debug( const std::string& fileToDebug, const std::string& symbol ) { bool debug = false; { bool debugEnabled = false; size_t filesSize = 0; size_t symbolsSize = 0; bool symbolFound = false; { itk::MutexLockHolder lock(*d->m_Mutex); debugEnabled = d->m_DebugEnabled; filesSize = d->m_FilesToDebug.size(); symbolsSize = d->m_SymbolsToDebug.size(); symbolFound = d->m_SymbolsToDebug.find(symbol) != d->m_SymbolsToDebug.end(); } if( debugEnabled ) { if( filesSize == 0 ) debug = true; else debug = DebugFile(fileToDebug); // ok debug is determined so far, now check if symbol set if( symbolsSize > 0 ) { debug = symbolFound; } else { // do not show symbol debug output if no symbols are set at all if( !symbol.empty() ) debug = false; } } } return debug; } void EndoDebug::SetDebugEnabled(bool _DebugEnabled) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_DebugEnabled = _DebugEnabled; } } void EndoDebug::SetDebugImagesOutputDirectory(const std::string& _DebugImagesOutputDirectory) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_DebugImagesOutputDirectory = _DebugImagesOutputDirectory; } } bool EndoDebug::GetDebugEnabled() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_DebugEnabled; } } void EndoDebug::SetShowImagesInDebug(bool _ShowImagesInDebug) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_ShowImagesInDebug = _ShowImagesInDebug; } } bool EndoDebug::GetShowImagesInDebug() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_ShowImagesInDebug; } } void EndoDebug::SetShowImagesTimeOut(size_t _ShowImagesTimeOut) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_ShowImagesTimeOut = _ShowImagesTimeOut; } } std::string EndoDebug::GetDebugImagesOutputDirectory() const { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_DebugImagesOutputDirectory; } } bool EndoDebug::GetShowImagesTimeOut() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_ShowImagesTimeOut; } } void EndoDebug::SetLogFile( const std::string& file ) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_Stream.open ( file.c_str(), std::ios::out | std::ios::app); } } void EndoDebug::ShowMessage( const std::string& message ) { { itk::MutexLockHolder lock(*d->m_Mutex); if(d->m_Stream.is_open()) { char *timestr; struct tm *newtime; time_t aclock; time(&aclock); newtime = localtime(&aclock); timestr = asctime(newtime); d->m_Stream << timestr << ", " << message; } else std::cout << message << std::flush; } } } diff --git a/Modules/CameraCalibration/mitkEndoDebug.h b/Modules/CameraCalibration/mitkEndoDebug.h index 98301ce900..303b102db5 100644 --- a/Modules/CameraCalibration/mitkEndoDebug.h +++ b/Modules/CameraCalibration/mitkEndoDebug.h @@ -1,232 +1,247 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkEndoDebug_h #define mitkEndoDebug_h #include #include #include #include #include namespace mitk { /// /// again d pointer impl /// struct EndoDebugData; /// /// class responsible for handling debug matters /// in endotracking /// struct mitkCameraCalibration_EXPORT EndoDebug { /// /// singleton class /// static EndoDebug& GetInstance(); /// /// helper function getting unique file name /// static std::string GetUniqueFileName( const std::string& dir, const std::string& ext="jpg" ); /// /// set if debug is enabled at all /// void SetDebugEnabled(bool _DebugEnabled); /// /// \return true if debug should be enabled /// bool GetDebugEnabled(); /// /// set if debug is enabled at all /// void SetShowImagesInDebug(bool _ShowImagesInDebug); /// /// \return true if debug should be enabled /// bool GetShowImagesInDebug(); /// /// set if debug is enabled at all /// void SetShowImagesTimeOut(size_t _ShowImagesTimeOut); /// /// \return true if debug should be enabled /// bool GetShowImagesTimeOut(); /// /// sets an output directory. if set all images that are shown are also written to that /// output dir /// void SetDebugImagesOutputDirectory(const std::string& _DebugImagesOutputDirectory); /// /// \return true if debug should be enabled /// std::string GetDebugImagesOutputDirectory() const; /// /// \return the basename of a file without path /// std::string GetFilenameWithoutExtension(const std::string& s); /// /// add a file to debug ( if one or more files are set ) /// only those files will be debugged when using the macros /// below. e.g. call AddFileToDebug("MyClass.cpp"), then /// statements like endodebug(...) will be evaluated in /// MyClass.cpp and nowhere else /// void AddFileToDebug(const std::string& fileToDebug); /// /// same as files to debug, but the user can provide /// any symbol string. if one or more symbols /// are set only for these symbols Debug() will return true /// void AddSymbolToDebug(const std::string& symbolToDebug); /// /// \return true if file should be debugged /// bool DebugFile( const std::string& fileToDebug ); /// /// \return true if symbol should be debugged /// bool DebugSymbol( const std::string& symbolToDebug ); /// /// \return the all in all status if debug output /// should be generated /// bool Debug( const std::string& fileToDebug, const std::string& symbol="" ); /// /// set a log file. if a log file is set and debug is activated all messages will be appended to that file /// void SetLogFile( const std::string& file ); /// /// shows a message or writes it to a log file if a file is set (and is valid for writing) /// void ShowMessage( const std::string& message ); /// /// init defaults /// EndoDebug(); /// /// delete d pointer /// virtual ~EndoDebug(); private: /// /// d pointer /// EndoDebugData* d; }; } // DISABLE DEBUGGING FOR RELEASE MODE ON WINDOWS #if (defined(WIN32) && !defined(_DEBUG)) || defined(NDEBUG) #define endodebugmarker #define endodebug(msg) #define endodebugvar(var) #define endodebugsymbol(var, mSymbol) #define endodebugimg(imgVariableName) #define endodebugbegin if( false ) { #define endodebugend } #else /// /// macro for debugging purposes /// #define endodebugmarker\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::ostringstream ___ostringstream; \ ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " << __FUNCTION__ << std::endl;\ mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ } /// /// macro for debugging purposes /// #define endodebug(msg)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::ostringstream ___ostringstream; \ ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " << msg << std::endl;\ mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ } /// /// macro for debugging variables /// #define endodebugvar(var)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::ostringstream ___ostringstream; \ ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " #var " = " << var << std::endl;\ mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ } /// /// macro for debugging a variable as symbol /// #define endodebugsymbol(var, mSymbol)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__, mSymbol) ) \ { \ std::ostringstream ___ostringstream; \ ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " #var " = " << var << std::endl;\ mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ } /// /// macro for showing cv image if in debug mode /// highgui.h must be included before /// #define endodebugimg(imgVariableName)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) \ && mitk::EndoDebug::GetInstance().GetShowImagesInDebug() \ && (imgVariableName).cols > 0 && (imgVariableName).rows > 0 && (imgVariableName).data) \ { \ std::ostringstream ___ostringstream; \ ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": Showing " #imgVariableName << std::endl; \ mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ std::string outputFile = mitk::EndoDebug::GetInstance().GetDebugImagesOutputDirectory(); \ if( !outputFile.empty() ) \ {\ outputFile = mitk::EndoDebug::GetInstance().GetUniqueFileName(outputFile, "jpg");\ cv::imwrite(outputFile, imgVariableName);\ }\ cv::imshow( "Debug", imgVariableName ); \ cv::waitKey( mitk::EndoDebug::GetInstance().GetShowImagesTimeOut() ); \ } /// /// macro for a section that should only be executed if debugging is enabled /// #define endodebugbegin \ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { /// /// macro for a section that should only be executed if debugging is enabled /// #define endodebugend \ } #endif #endif // mitkEndoDebug_h diff --git a/Modules/CameraCalibration/mitkEndoMacros.h b/Modules/CameraCalibration/mitkEndoMacros.h index ea450aec64..1597a5d9db 100644 --- a/Modules/CameraCalibration/mitkEndoMacros.h +++ b/Modules/CameraCalibration/mitkEndoMacros.h @@ -1,81 +1,96 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkEndoMacros_h #define mitkEndoMacros_h /// /// COLLECTION OF MACROS FOR THE ENDOTRACKING MODULE /// /// /// multiplexing for cv mats /// #define endoAccessCvMat(function, T, arg1, arg2) \ if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else if( arg2.type() == cv::DataType::type ) \ function( arg1, arg2 ); \ else \ throw std::invalid_argument("Unknown type for cv::Mat"); /// /// exec an algorithm with 1 output argument /// #define endoExec(macroAlgName, macroOutputType, macroOutputVarName, ...)\ macroOutputType macroOutputVarName;\ { \ macroAlgName _macroAlgName(__VA_ARGS__, ¯oOutputVarName);\ _macroAlgName.Update();\ } /// /// exec an algorithm with 2 output argument /// #define endoExec2(macroAlgName, macroOutputType1, macroOutputVarName1, macroOutputType2, macroOutputVarName2, ...)\ macroOutputType1 macroOutputVarName1;\ macroOutputType1 macroOutputVarName1;\ { \ macroAlgName _macroAlgName(__VA_ARGS__, ¯oOutputVarName1, ¯oOutputVarName2);\ _macroAlgName.Update();\ } /// /// an assert macro for throwing exceptions from an assert /// #define endoAssert(a) if(!(a)) { \ std::ostringstream s; \ s << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " \ << __LINE__ << ", failed: " << #a; \ throw std::invalid_argument(s.str()); } /// /// same as above but with an output error stream /// use it like this: endoAssertMsg( file.read() == true, file << "could not be read" ); /// #define endoAssertMsg(a, msg) if(!(a)) { \ std::ostringstream s; \ s << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " \ << __LINE__ << ": " << msg; \ throw std::invalid_argument(s.str()); \ } /// /// definition of the corresponding directory separator /// #ifdef WIN32 static const std::string DIR_SEPARATOR = "\\"; #else static const std::string DIR_SEPARATOR = "/"; #endif #endif // mitkEndoMacros_h diff --git a/Modules/CameraCalibration/mitkEpsilon.h b/Modules/CameraCalibration/mitkEpsilon.h index e8012b19e0..ae17b947fc 100644 --- a/Modules/CameraCalibration/mitkEpsilon.h +++ b/Modules/CameraCalibration/mitkEpsilon.h @@ -1,13 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkEpsilon_h #define mitkEpsilon_h namespace mitk { /// /// typdef for Epsilon /// typedef double Epsilon; } // namespace mitk #endif // mitkEpsilon_h diff --git a/Modules/CameraCalibration/mitkObservable.h b/Modules/CameraCalibration/mitkObservable.h index f1722f0486..b46e325958 100644 --- a/Modules/CameraCalibration/mitkObservable.h +++ b/Modules/CameraCalibration/mitkObservable.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkObservable_h #define mitkObservable_h #include namespace mitk { /// /// filter "Observable" interface /// class Observable { public: /// /// this class garantuees to call Update() on /// all observer if it changes /// if you need more then one observer bundle /// the algorithms in a BatchAlgorithm /// virtual void SetObserver( Algorithm* _Algorithm ) = 0; }; } // namespace mitk #endif // mitkObservable_h diff --git a/Modules/CameraCalibration/mitkStringFromCvMat.h b/Modules/CameraCalibration/mitkStringFromCvMat.h index 53959f694c..e29b547b39 100644 --- a/Modules/CameraCalibration/mitkStringFromCvMat.h +++ b/Modules/CameraCalibration/mitkStringFromCvMat.h @@ -1,77 +1,92 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkStringFromCvMat_h #define mitkStringFromCvMat_h #include #include #include #include #include #include namespace mitk { /// /// create a vnl_matrix from a cv mat /// class StringFromCvMat: virtual public Algorithm { public: /// /// init default values and save references /// StringFromCvMat( const cv::Mat* _CvMat, std::string* _String): m_CvMat(_CvMat), m_String(_String) { } /// /// cv mat to vnl matrix with known cv type /// template void ToString( std::string& string, const cv::Mat& mat ) { std::ostringstream s; for(int i=0; i(i,j) << " "; } s << T_Delim; } string = s.str(); } void SetMatrix( const cv::Mat* _CvMat ) { m_CvMat = _CvMat; } /// /// executes the Algorithm /// void Update() { endoAccessCvMat( ToString, '\n', (*m_String), (*m_CvMat) ); } private: /// /// StringFromCvMat input member variable /// const cv::Mat* m_CvMat; /// /// StringFromCvMat output member variable /// std::string* m_String; }; } // namespace mitk #endif // mitkStringFromCvMat_h diff --git a/Modules/CameraCalibration/mitkTransform.cpp b/Modules/CameraCalibration/mitkTransform.cpp index 50b7dcae91..d458cf7f29 100644 --- a/Modules/CameraCalibration/mitkTransform.cpp +++ b/Modules/CameraCalibration/mitkTransform.cpp @@ -1,723 +1,738 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkTransform.h" #include #include #include #include #include #include namespace mitk { // DO NOT CHANGE THE VALUES OF THESE CONSTANTS!! const std::string Transform::UNKNOWN_TYPE = "Unknown type"; const std::string Transform::ENDOSCOPE_SCOPE_TOOL = "Endoscope scope tool"; const std::string Transform::ENDOSCOPE_CAM_TOOL = "Endoscope camera tool"; const std::string Transform::CHESSBOARD_TOOL = "Chessboard tool"; const std::string Transform::POINTER_TOOL = "Pointer tool"; const std::string Transform::POINTER_TO_CHESSBOARD_ORIGIN = "Pointer to chessboard origin"; const std::string Transform::POINTER_TO_CHESSBOARD_X_SUPPORT_POINT = "Pointer to chessboard X support origin"; const std::string Transform::POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT = "Pointer to chessboard Y support origin"; const std::string Transform::BOARD_TO_BOARD_TOOL = "Board to board tool"; const std::string Transform::REFERENCE_CAMERA_TRANSFORM = "Reference camera transform"; const std::string Transform::REFERENCE_SCOPE_TRANSFORM = "Reference scope transform"; const std::string Transform::EYE_TO_HAND_TRANSFORM = "Eye to hand transform"; const std::string Transform::CAMERA_EXTRINSICS = "Camera extrinsics"; Transform::Transform() : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } Transform::Transform(const mitk::NavigationData* nd) : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { m_NavData->Graft(nd); } Transform::Transform(const std::string& s) : m_NavData(mitk::NavigationData::New()), m_Type( s ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } void Transform::Copy(const mitk::NavigationData* nd) { (const_cast(m_NavData.GetPointer()))->Graft(nd); } void Transform::Concatenate( mitk::Transform* transform ) { vnl_matrix_fixed mat = transform->GetMatrix(); mat = mat * this->GetMatrix(); // this->SetMatrix( mat ); } void Transform::Concatenate( const vnl_matrix_fixed& transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Concatenate( const vtkMatrix4x4* transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Reset() { mitk::NavigationData::Pointer nd = NavigationData::New(); this->Copy( nd ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { m_NavData->SetOrientation(orientation); this->Modified(); } void Transform::SetTranslation( const vnl_vector_fixed& transl) { mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); this->Modified(); } void Transform::SetTranslation( float* array ) { vnl_vector_fixed vec; for(unsigned int i=0; iSetTranslation( vec ); } void Transform::SetRotation( float* array ) { vnl_matrix_fixed mat; unsigned int row = 0; unsigned int col = 0; for(unsigned int i=0; i 0 && i % 3 == 0 ) { ++row; col = 0; } mat(row,col) = array[i]; ++col; } this->SetRotation( mat ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { vnl_vector_fixed qvec; VnlVectorFixedCaster caster( &orientation, &qvec ); caster.Update(); mitk::Quaternion p( qvec ); this->SetOrientation( p ); } vnl_vector_fixed Transform::GetVnlDoubleTranslation() const { vnl_vector_fixed vecFloat = this->GetVnlTranslation(); vnl_vector_fixed vecDouble; VnlVectorFixedCaster caster( &vecFloat, &vecDouble ); caster.Update(); return vecDouble; } void Transform::SetTranslation( const vnl_vector& transl) { vnl_vector_fixed dTransl(transl); vnl_vector_fixed fTransl; VnlVectorFixedCaster caster( &dTransl, &fTransl ); caster.Update(); this->SetTranslation( fTransl ); } vnl_quaternion Transform::GetVnlDoubleQuaternion() const { mitk::Quaternion fOrientation = this->GetOrientation(); vnl_quaternion dOrientation; VnlVectorFixedCaster caster( &fOrientation, &dOrientation ); caster.Update(); return dOrientation; } void Transform::FromCSVFile(const std::string& file) { std::ifstream csvFile (file.c_str()); endoAssert ( csvFile.fail() == false ); mitk::Transform::Pointer transform = mitk::Transform::New(); vnl_matrix_fixed mat; std::string line; mitk::ScalarType d = 0.0f; int row=0,column = 0; while (std::getline (csvFile, line)) { std::istringstream linestream(line); std::string item; column = 0; while (std::getline (linestream, item, ',')) { std::istringstream number; number.str(item); number >> d; mat(row, column) = d; ++column; } ++row; } endoAssert( row == 4 && column == 4 ); transform->SetMatrix( mat ); this->SetNavigationData( transform->GetNavigationData() ); // modified is called in SetNavigationData } std::string Transform::ToCSVString() const { std::ostringstream s; s.precision(12); vnl_matrix_fixed mat = this->GetMatrix(); for( unsigned int j=0; j mat = this->GetMatrix(); s << varname << " = ["; for( unsigned int j=0; jGraft(transform->GetNavigationData()); m_Type = transform->GetType(); } mitk::Transform::Pointer Transform::Clone() const { Transform::Pointer copy = Transform::New(); copy->Copy( this ); return copy; } void Transform::SetMatrix( const vtkMatrix4x4* mat) { vnl_matrix_fixed vnlMat; for(unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) vnlMat(i,j) = mat->GetElement(i, j); this->SetMatrix( vnlMat ); } void Transform::ToCSVFile(const std::string& file) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToCSVString(); csvFile.close(); } void Transform::ToMatlabFile(const std::string& file , const std::string& varname) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToMatlabString(varname); csvFile.close(); } void Transform::SetNavigationData( const mitk::NavigationData* naviData ) { endoAssert( naviData != 0 ); m_NavData->Graft( naviData ); this->Modified(); } void Transform::SetRotation( vnl_matrix_fixed& mat) { this->m_NavData->SetOrientation( mitk::Quaternion(mat) ); this->Modified(); } void Transform::SetRotation( vnl_matrix& mat) { vnl_matrix_fixed tmp(mat); this->SetRotation( tmp ); } void Transform::SetPosition( const mitk::Point3D& transl) { this->SetTranslation( transl.GetVnlVector() ); } void Transform::SetTranslation( double array[3] ) { mitk::Point3D p; for(unsigned int i = 0; i < 3; ++i) p.SetElement(i, array[i]); this->SetTranslation( p.GetVnlVector() ); } void Transform::SetRotation( double array[3][3] ) { vnl_matrix_fixed mat; for(unsigned int i = 0; i < 3; ++i) for(unsigned int j = 0; j < 3; ++j) mat(i, j) = array[i][j]; this->SetRotation( mat ); } void Transform::Invert() { vnl_matrix_fixed tmp(this->GetMatrix()); this->SetMatrix( vnl_inverse( tmp ) ); } void Transform::SetMatrix( const vnl_matrix_fixed& mat) { // set translation first vnl_vector transl = mat.get_column(3); mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); // set rotation vnl_matrix_fixed rotMatFixed( mat.extract(3,3)); this->SetRotation(rotMatFixed); } bool Transform::IsValid() const { return m_NavData->IsDataValid(); } void Transform::SetTranslation( const cv::Mat& transl) { vnl_vector vec(3); VnlVectorFromCvMat _VnlVectorFromCvMat( &transl, &vec ); _VnlVectorFromCvMat.Update(); this->SetTranslation( vnl_vector_fixed( vec ) ); } void Transform::SetRotation( const cv::Mat& mat ) { vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &mat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation(vnlMatFixed); } void Transform::SetRotationVector( const cv::Mat& rotVec ) { cv::Mat rotMat; cv::Rodrigues( rotVec, rotMat ); vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &rotMat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation( vnlMatFixed ); } //# getter mitk::NavigationData::Pointer Transform::GetNavigationData() const { return m_NavData; } mitk::Point3D Transform::GetTranslation() const { return m_NavData->GetPosition(); } mitk::Point3D Transform::GetPosition() const { return m_NavData->GetPosition(); } mitk::Quaternion Transform::GetOrientation() const { return m_NavData->GetOrientation(); } void Transform::GetMatrix(vtkMatrix4x4* matrix) const { vnl_matrix_fixed vnlMat = this->GetMatrix(); for(unsigned int i=0; iSetElement(i,j, vnlMat(i,j)); } void Transform::GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const { vnl_matrix vnlRotation = this->GetVnlRotationMatrix().as_matrix(); // normalize rows of rotation matrix vnlRotation.normalize_rows(); vnl_matrix vnlInverseRotation(3,3); // invert rotation vnlInverseRotation = vnl_matrix_inverse(vnlRotation); vnl_vector vnlTranslation = this->GetPosition().GetVnlVector(); // rotate translation vector by inverse rotation P = P' vnlTranslation = vnlInverseRotation * vnlTranslation; vnlTranslation *= -1; // save -P' // set position mitk::Transform::Pointer tmp = mitk::Transform::New(); tmp->SetTranslation( vnlTranslation ); tmp->SetRotation( vnlRotation ); tmp->GetMatrix(matrix); } //# cv getter cv::Mat Transform::GetCvTranslation() const { cv::Mat mat; vnl_vector vec = this->GetVnlTranslation().as_vector(); endodebugvar( vec ) CvMatFromVnlVector _CvMatFromVnlVector(&vec, &mat); _CvMatFromVnlVector.Update(); return mat; } cv::Mat Transform::GetCvRotationMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); endodebugvar( vec ) CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetMatrix().as_matrix(); CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvRotationVector() const { cv::Mat rotVec(3,1,cv::DataType::type); cv::Rodrigues( this->GetCvRotationMatrix(), rotVec ); return rotVec; } //# vnl getter vnl_vector_fixed Transform::GetVnlTranslation() const { vnl_vector_fixed vec(m_NavData->GetPosition() .GetVnlVector()); return vec; } vnl_matrix_fixed Transform::GetVnlRotationMatrix() const { return m_NavData->GetOrientation().rotation_matrix_transpose(); } vnl_matrix_fixed Transform::GetVnlDoubleMatrix() const { vnl_matrix_fixed mat = this->GetMatrix(); vnl_matrix_fixed doubleMat; for(unsigned int i=0; i( mat(i,j) ); return doubleMat; } vnl_matrix_fixed Transform::GetMatrix() const { vnl_vector_fixed transl = this->GetVnlTranslation(); vnl_matrix_fixed rot = this->GetVnlRotationMatrix(); vnl_matrix_fixed homMat; homMat.set_identity(); //std::cout << homMat << std::endl; for(unsigned int i=0; i rotMat = this->GetVnlRotationMatrix().transpose(); this->SetRotation( rotMat ); } void Transform::SetValid( bool valid ) { if( m_NavData->IsDataValid() == valid ) return; m_NavData->SetDataValid( valid ); this->Modified(); } std::string mitk::Transform::ToString() const { std::ostringstream s; s.precision(12); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); s << "Translation: [" << position[0] << ", " << position[1] << ", " << position[2] << "]"; s << ", orientation: [" << orientation[0] << ", " << orientation[1] << ", " << orientation[2] << ", " << orientation[3] << "]"; s << ", valid: [" << (this->IsValid()? "true": "false") << "]"; return s.str(); } void mitk::Transform::ToXML(TiXmlElement* elem) const { std::string value = elem->ValueStr(); if(value.empty()) elem->SetValue(this->GetNameOfClass()); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); mitk::NavigationData::CovarianceMatrixType matrix; matrix.SetIdentity(); matrix = m_NavData->GetCovErrorMatrix(); bool hasPosition = true; hasPosition = m_NavData->GetHasPosition(); bool hasOrientation = true; hasOrientation = m_NavData->GetHasOrientation(); bool dataValid = false; dataValid = m_NavData->IsDataValid(); mitk::NavigationData::TimeStampType timestamp=0.0; elem->SetAttribute("Type", m_Type); elem->SetDoubleAttribute("Time", timestamp); elem->SetDoubleAttribute("X", position[0]); elem->SetDoubleAttribute("Y", position[1]); elem->SetDoubleAttribute("Z", position[2]); elem->SetDoubleAttribute("QX", orientation[0]); elem->SetDoubleAttribute("QY", orientation[1]); elem->SetDoubleAttribute("QZ", orientation[2]); elem->SetDoubleAttribute("QR", orientation[3]); elem->SetDoubleAttribute("C00", matrix[0][0]); elem->SetDoubleAttribute("C01", matrix[0][1]); elem->SetDoubleAttribute("C02", matrix[0][2]); elem->SetDoubleAttribute("C03", matrix[0][3]); elem->SetDoubleAttribute("C04", matrix[0][4]); elem->SetDoubleAttribute("C05", matrix[0][5]); elem->SetDoubleAttribute("C10", matrix[1][0]); elem->SetDoubleAttribute("C11", matrix[1][1]); elem->SetDoubleAttribute("C12", matrix[1][2]); elem->SetDoubleAttribute("C13", matrix[1][3]); elem->SetDoubleAttribute("C14", matrix[1][4]); elem->SetDoubleAttribute("C15", matrix[1][5]); if (dataValid) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (hasOrientation) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (hasPosition) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); } void mitk::Transform::FromXML(TiXmlElement* elem) { assert(elem); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); mitk::NavigationData::TimeStampType timestamp = -1; mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); std::string type = Transform::UNKNOWN_TYPE; elem->QueryStringAttribute("Type", &type); elem->QueryDoubleAttribute("Time",×tamp); // position and orientation is mandatory! if(elem->QueryFloatAttribute("X", &position[0]) != TIXML_SUCCESS) throw std::invalid_argument("No X position found in xml"); if(elem->QueryFloatAttribute("Y", &position[1]) != TIXML_SUCCESS) throw std::invalid_argument("No Y position found in xml"); if(elem->QueryFloatAttribute("Z", &position[2]) != TIXML_SUCCESS) throw std::invalid_argument("No Z position found in xml"); if(elem->QueryFloatAttribute("QX", &orientation[0]) != TIXML_SUCCESS) throw std::invalid_argument("No QX orientation found in xml"); if(elem->QueryFloatAttribute("QY", &orientation[1]) != TIXML_SUCCESS) throw std::invalid_argument("No QY orientation found in xml"); if(elem->QueryFloatAttribute("QZ", &orientation[2]) != TIXML_SUCCESS) throw std::invalid_argument("No QZ orientation found in xml"); if(elem->QueryFloatAttribute("QR", &orientation[3]) != TIXML_SUCCESS) throw std::invalid_argument("No QR orientation found in xml"); elem->QueryFloatAttribute("C00", &matrix[0][0]); elem->QueryFloatAttribute("C01", &matrix[0][1]); elem->QueryFloatAttribute("C02", &matrix[0][2]); elem->QueryFloatAttribute("C03", &matrix[0][3]); elem->QueryFloatAttribute("C04", &matrix[0][4]); elem->QueryFloatAttribute("C05", &matrix[0][5]); elem->QueryFloatAttribute("C10", &matrix[1][0]); elem->QueryFloatAttribute("C11", &matrix[1][1]); elem->QueryFloatAttribute("C12", &matrix[1][2]); elem->QueryFloatAttribute("C13", &matrix[1][3]); elem->QueryFloatAttribute("C14", &matrix[1][4]); elem->QueryFloatAttribute("C15", &matrix[1][5]); int tmpval = 0; elem->QueryIntAttribute("Valid", &tmpval); if (tmpval == 0) dataValid = false; else dataValid = true; tmpval = 0; elem->QueryIntAttribute("hO", &tmpval); if (tmpval == 0) hasOrientation = false; else hasOrientation = true; tmpval = 0; elem->QueryIntAttribute("hP", &tmpval); if (tmpval == 0) hasPosition = false; else hasPosition = true; nd->SetTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); m_NavData = nd; m_Type = type; this->Modified(); } } // namespace mitk std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p) { os << p->ToString(); return os; } diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h index 75af440ef7..b2fa9769e0 100644 --- a/Modules/CameraCalibration/mitkTransform.h +++ b/Modules/CameraCalibration/mitkTransform.h @@ -1,288 +1,303 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKTRANSFORM_H #define MITKTRANSFORM_H #include #include #include #include #include #include #include #include #include #include namespace mitk { /// /// \brief class representing a transfrom in 3D /// /// internally it stores a mitk navigation data. this is more /// or less a wrapper for navigation data for easy casting /// between opencv/vnl/mitk/xml representations of transform /// data /// class mitkCameraCalibration_EXPORT Transform: public itk::Object, public XMLSerializable { public: mitkClassMacro(Transform, itk::Object); itkFactorylessNewMacro(Transform); mitkNewMacro1Param(Transform, const mitk::NavigationData*); mitkNewMacro1Param(Transform, const std::string&); /// /// constants describing the type of transform /// represented here /// static const std::string UNKNOWN_TYPE; static const std::string ENDOSCOPE_SCOPE_TOOL; static const std::string ENDOSCOPE_CAM_TOOL; static const std::string CHESSBOARD_TOOL; static const std::string POINTER_TOOL; static const std::string POINTER_TO_CHESSBOARD_ORIGIN; static const std::string POINTER_TO_CHESSBOARD_X_SUPPORT_POINT; static const std::string POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT; static const std::string BOARD_TO_BOARD_TOOL; static const std::string REFERENCE_CAMERA_TRANSFORM; static const std::string REFERENCE_SCOPE_TRANSFORM; static const std::string EYE_TO_HAND_TRANSFORM; static const std::string CAMERA_EXTRINSICS; itkGetConstMacro(Type, std::string); itkSetMacro(Type, std::string&); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::Transform* transform ); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::NavigationData* transform ); /// /// Inverts the rotation of this transform /// (Polaris navigation Data have inverted rotation /// so you may want to call this function when using /// polaris data) /// void TransposeRotation(); /// /// get a copy of this transform /// mitk::Transform::Pointer Clone() const; /// /// concatenate this transform with the given one, /// i.e. this transform is done first, then transform /// ( if x is this transform, y is transform, then this will be y*x) /// post multiply semantics! /// \see vtkTransform /// void Concatenate( mitk::Transform* transform ); /// /// same as above with vnl mat argument /// void Concatenate( const vnl_matrix_fixed& transform ); /// /// same as above with vtk mat argument /// void Concatenate( const vtkMatrix4x4* transform ); /// /// invert this transform /// void Invert(); /// /// resets the internal variables except type /// void Reset(); /// /// read from xml /// void FromXML(TiXmlElement* elem); /// /// read csv file /// void FromCSVFile(const std::string& file); /// /// grafts the data from naviData to this transform /// void SetNavigationData( const mitk::NavigationData* naviData ); /// /// method to set orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set double valued orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set translation /// void SetTranslation( const vnl_vector_fixed& transl); /// /// method to set a vector of doubles as translation /// void SetTranslation( const vnl_vector& transl); /// /// method to set a mitk::Point3D as position /// void SetPosition( const mitk::Point3D& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( vnl_matrix_fixed& mat); /// /// sets rotation with a non fixed rotation matrix /// void SetRotation( vnl_matrix& mat); /// /// sets rotation and translation with a transformation matrix /// void SetMatrix( const vnl_matrix_fixed& mat); /// /// sets rotation and translation with a vtk transformation matrix /// void SetMatrix( const vtkMatrix4x4* mat); /// /// sets translation from a POD vector /// void SetTranslation( float* array ); /// /// sets translation from a POD vector. this must be a /// 3x3=9 sized vector in row major format (first row = first /// three elements) /// void SetRotation( float* array ); /// /// sets translation from a POD vector /// void SetTranslation( double array[3] ); /// /// sets translation from a POD vector /// void SetRotation( double array[3][3] ); /// /// method to set translation by cv vector /// void SetTranslation( const cv::Mat& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( const cv::Mat& mat ); /// /// sets rotation with a rodrigues rotation vector /// void SetRotationVector( const cv::Mat& rotVec); /// /// \return the navigation data that stores all information /// mitk::NavigationData::Pointer GetNavigationData() const; /// /// calls navigationdata::GetPosition() /// mitk::Point3D GetPosition() const; /// /// same as GetPosition /// mitk::Point3D GetTranslation() const; /// /// calls navigationdata::IsValid() /// bool IsValid() const; /// /// calls navigationdata::SetValid() /// void SetValid(bool valid); /// /// calls navigationdata::GetOrientation() /// mitk::Quaternion GetOrientation() const; /// /// \return the homogeneous matrix representing this transform /// vnl_matrix_fixed GetMatrix() const; /// /// \return the homogeneous vtk matrix representing this transform /// void GetMatrix(vtkMatrix4x4* matrix) const; /// /// \return the homogeneous vtk matrix representing this transform /// in !OpenGL! left handed coordinate system /// void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const; /// /// create xml representation /// void ToXML(TiXmlElement* elem) const; /// /// create string representation /// std::string ToString() const; /// /// create string csv representation (only the transformation values!!!!) /// std::string ToCSVString() const; /// /// create matlab representation /// std::string ToMatlabString(const std::string& varname="transform", bool printLastRow=true) const; /// /// write csv representation to file (only the transformation values!!!!) /// void ToCSVFile(const std::string& file) const; /// /// write matlab representation to file /// void ToMatlabFile(const std::string& file , const std::string& varname="transform") const; /// /// conversion to cv types /// cv::Mat GetCvTranslation() const; cv::Mat GetCvRotationVector() const; cv::Mat GetCvRotationMatrix() const; cv::Mat GetCvMatrix() const; /// /// conversion to vnl types /// vnl_vector_fixed GetVnlTranslation() const; vnl_vector_fixed GetVnlDoubleTranslation() const; vnl_quaternion GetVnlDoubleQuaternion() const; vnl_matrix_fixed GetVnlRotationMatrix() const; vnl_matrix_fixed GetVnlDoubleMatrix() const; protected: Transform(); Transform(const mitk::NavigationData* nd); Transform(const std::string& s); // everything is stored here mitk::NavigationData::Pointer m_NavData; /// /// saves the type of the transform (Default is UNKNOWN_TYPE) /// std::string m_Type; }; } // namespace mitk mitkCameraCalibration_EXPORT std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p); #endif // MITKTRANSFORM_H diff --git a/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h b/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h index a2893c1d78..f8e1817f86 100644 --- a/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h +++ b/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h @@ -1,63 +1,78 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkVnlMatrixFromCvMat_h #define mitkVnlMatrixFromCvMat_h #include #include #include #include #include namespace mitk { /// /// create a vnl_matrix from a cv mat /// template class VnlMatrixFromCvMat: virtual public Algorithm { public: /// /// init default values and save references /// VnlMatrixFromCvMat( const cv::Mat* _CvMat, vnl_matrix* _VnlMatrix): m_CvMat(_CvMat), m_VnlMatrix(_VnlMatrix) { } /// /// cv mat to vnl matrix with known cv type /// template void ToVnlMatrix( vnl_matrix& vnlMat, const cv::Mat& mat ) { vnlMat.set_size( mat.rows, mat.cols ); for(int i=0; i( mat.at(i,j) ); } /// /// executes the Algorithm /// void Update() { endoAccessCvMat( ToVnlMatrix, T, (*m_VnlMatrix), (*m_CvMat) ); } private: /// /// VnlMatrixFromCvMat input member variable /// const cv::Mat* m_CvMat; /// /// VnlMatrixFromCvMat output member variable /// vnl_matrix* m_VnlMatrix; }; } // namespace mitk #endif // mitkVnlMatrixFromCvMat_h diff --git a/Modules/CameraCalibration/mitkVnlVectorCaster.h b/Modules/CameraCalibration/mitkVnlVectorCaster.h index 39849334c0..e82670a47b 100644 --- a/Modules/CameraCalibration/mitkVnlVectorCaster.h +++ b/Modules/CameraCalibration/mitkVnlVectorCaster.h @@ -1,60 +1,75 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkVnlVectorCaster_h #define mitkVnlVectorCaster_h #include #include #include namespace mitk { /// /// class for casting vnl vectors to another basic type /// by means of static cast /// template class VnlVectorCaster: virtual public Algorithm { public: /// /// init default values and save references /// VnlVectorCaster( const vnl_vector* _InputVector, vnl_vector* _OutputVector): m_InputVector(_InputVector), m_OutputVector(_OutputVector) { } /// /// static update /// static void Update( const vnl_vector& _InputVector, vnl_vector& _OutputVector) { for( size_t i=0; i<_InputVector.size(); ++i ) _OutputVector[i] = static_cast( _InputVector[i] ); } /// /// executes the Algorithm /// void Update() { Update( *m_InputVector, *m_OutputVector ); } private: /// /// VnlVectorCaster input member variable /// const vnl_vector* m_InputVector; /// /// VnlVectorCaster output member variable /// vnl_vector* m_OutputVector; }; } // namespace mitk #endif // mitkVnlVectorCaster_h diff --git a/Modules/CameraCalibration/mitkVnlVectorFixedCaster.h b/Modules/CameraCalibration/mitkVnlVectorFixedCaster.h index 514afd6dd6..cf0dcf6439 100644 --- a/Modules/CameraCalibration/mitkVnlVectorFixedCaster.h +++ b/Modules/CameraCalibration/mitkVnlVectorFixedCaster.h @@ -1,50 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkVnlVectorFixedCaster_h #define mitkVnlVectorFixedCaster_h #include #include #include namespace mitk { /// /// class for casting vnl vectors to another basic type /// by means of static cast /// template class VnlVectorFixedCaster: virtual public Algorithm { public: /// /// init default values and save references /// VnlVectorFixedCaster( const vnl_vector_fixed* _InputVector, vnl_vector_fixed* _OutputVector): m_InputVector(_InputVector), m_OutputVector(_OutputVector) { } /// /// executes the Algorithm /// void Update() { for( size_t i=0; isize(); ++i ) (*m_OutputVector)[i] = static_cast( (*m_InputVector)[i] ); } private: /// /// VnlVectorFixedCaster input member variable /// const vnl_vector_fixed* m_InputVector; /// /// VnlVectorFixedCaster output member variable /// vnl_vector_fixed* m_OutputVector; }; } // namespace mitk #endif // mitkVnlVectorFixedCaster_h diff --git a/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h b/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h index f556b9782f..fe10ec2082 100644 --- a/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h +++ b/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h @@ -1,57 +1,72 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkVnlVectorFromCvMat_h #define mitkVnlVectorFromCvMat_h #include #include namespace mitk { /// /// create a vnl_vector from a cv mat /// template class VnlVectorFromCvMat: virtual public Algorithm { public: /// /// init default values and save references /// VnlVectorFromCvMat( const cv::Mat* _CvMat, vnl_vector* _VnlVector): m_VnlMatrixFromCvMat( _CvMat, &m_VnlMatrix ), m_VnlVector(_VnlVector) { } /// /// executes the Algorithm /// void Update() { m_VnlMatrixFromCvMat.Update(); if( m_VnlMatrix.rows() == 1 ) *m_VnlVector = m_VnlMatrix.get_row(0); else if( m_VnlMatrix.cols() == 1 ) *m_VnlVector = m_VnlMatrix.get_column(0); } private: /// /// VnlVectorFromCvMat input member variable /// vnl_matrix m_VnlMatrix; /// /// internal algorithm to get a vnl matrix from a cv mat /// VnlMatrixFromCvMat m_VnlMatrixFromCvMat; /// /// VnlVectorFromCvMat output member variable /// vnl_vector* m_VnlVector; }; } // namespace mitk #endif // mitkVnlVectorFromCvMat_h diff --git a/Modules/CameraCalibration/mitkXMLSerializable.cpp b/Modules/CameraCalibration/mitkXMLSerializable.cpp index 85b7dd5513..ee22318dd6 100644 --- a/Modules/CameraCalibration/mitkXMLSerializable.cpp +++ b/Modules/CameraCalibration/mitkXMLSerializable.cpp @@ -1,126 +1,141 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include "mitkEndoDebug.h" #include "mitkEndoMacros.h" #include namespace mitk { const std::string XMLSerializable::FILE_REFERENCE_ATTRIBUTE_NAME = "fileRef"; const std::string XMLSerializable::ROOT_NAME = "data"; void mitk::XMLSerializable::ToXMLFile(const std::string& file , const std::string& elemName) { TiXmlElement * rootElem=0; TiXmlElement * element=0; // determine element to write to std::string elementName = elemName; if(elementName.empty()) elementName = this->GetNameOfClass(); TiXmlDocument doc( file.c_str() ); bool loadOkay = doc.LoadFile(); // if the document already exists ... if(loadOkay) { // try to identify the XML element of this class as the root // or as the child of the root rootElem = doc.RootElement(); endoAssertMsg( rootElem, "No root element found in " << file ); // if root element represents this element remove the root if( rootElem->ValueStr() == elementName ) { doc.RemoveChild(rootElem); rootElem = 0; } else { // if it is a child of the root remove it too element = rootElem->FirstChildElement(elementName); if(element) rootElem->RemoveChild(element); } } else { // document did not exist, create new one with declration TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); doc.LinkEndChild( decl ); } m_XMLFileName = file; // create element (if the document already exists this element was removed) element = new TiXmlElement( elementName ); this->ToXML( element ); // if we do not have a root element create a new one if(!rootElem) rootElem = new TiXmlElement( ROOT_NAME ); // add the element node as child rootElem->LinkEndChild(element); // if no root element exists, add it now if(doc.RootElement() == 0) doc.LinkEndChild( rootElem ); if(!doc.SaveFile( file )) { std::ostringstream s; s << "File " << file << " could not be written. Please check permissions."; throw std::logic_error(s.str()); } } std::string mitk::XMLSerializable::GetXMLFileName() const { return m_XMLFileName; } void mitk::XMLSerializable::FromXMLFile(const std::string& file , const std::string& elemName) { endodebug( "Trying to read from " << file ) TiXmlDocument doc( file.c_str() ); bool loadOkay = doc.LoadFile(); if(!loadOkay) { std::ostringstream s; s << "File " << file << " could not be loaded!"; throw std::logic_error(s.str().c_str()); } m_XMLFileName = file; TiXmlElement* elem = doc.FirstChildElement(); endoAssertMsg( elem, "No root element found" ); // determine element to read from std::string elementName = elemName; if(elementName.empty()) elementName = this->GetNameOfClass(); // try again with the first element if(strcmp(elem->Value(), elementName.c_str()) != 0) elem = elem->FirstChildElement(elementName.c_str()); endoAssertMsg( elem, "No child element \"" << elementName << "\" found in " << file ); // if theres an attribute as file reference try to load the class // from that file std::string filename; if(elem->QueryStringAttribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str(), &filename) == TIXML_SUCCESS) { if( !itksys::SystemTools::FileIsFullPath(filename.c_str()) ) filename = itksys::SystemTools::GetFilenamePath(file) + "/" + filename; this->FromXMLFile(filename); return; // exit! } this->FromXML( elem ); } } diff --git a/Modules/CameraCalibration/mitkXMLSerializable.h b/Modules/CameraCalibration/mitkXMLSerializable.h index 9f5ad5b356..19a67016a5 100644 --- a/Modules/CameraCalibration/mitkXMLSerializable.h +++ b/Modules/CameraCalibration/mitkXMLSerializable.h @@ -1,77 +1,92 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKXMLSerializable_H #define MITKXMLSerializable_H #include #include #include #include #include namespace mitk { /// /// \brief interface for all classes able to write themselves to XML files /// class mitkCameraCalibration_EXPORT XMLSerializable { public: /// /// value of the special tag for file references /// if this is attribute is found the class /// will be loaded from the file in the attributes value /// static const std::string FILE_REFERENCE_ATTRIBUTE_NAME; /// /// the name of the root node that is created when the element is saved /// static const std::string ROOT_NAME; /// /// the tag value will be equals to the class name (function /// implemented by the itkTypeMacro) /// virtual const char* GetNameOfClass() const = 0; /// /// write your values here to elem /// virtual void ToXML(TiXmlElement* elem) const = 0; /// /// read your values here from elem /// virtual void FromXML(TiXmlElement* elem) = 0; /// /// tries to write the xml data obtained in ToXML() to file /// virtual void ToXMLFile(const std::string& file , const std::string& elemName=""); /// /// loads the XML file and calls FromXML() /// takes the first child of the document /// if this root node value is not equal to GetNameOfClass() /// the method will try to find the first children of the root /// node with the value of GetNameOfClass() /// if elemName is not empty then this value will be used instead /// of GetNameOfClass() /// if this node is found it will check if an attribute named /// FILE_REFERENCE_ATTRIBUTE_NAME is found: in this case /// the method calls itself with this attributes value as parameter /// virtual void FromXMLFile(const std::string& file , const std::string& elemName=""); /// /// \see m_XMLFileName /// std::string GetXMLFileName() const; private: /// /// saves the xmlfile name set for this serializable ( in FromXMLFile() ) /// std::string m_XMLFileName; }; } #endif diff --git a/Modules/ClippingTools/mitkClippingPlaneDeformationTool.cpp b/Modules/ClippingTools/mitkClippingPlaneDeformationTool.cpp index b7ae93c585..364a054ee4 100644 --- a/Modules/ClippingTools/mitkClippingPlaneDeformationTool.cpp +++ b/Modules/ClippingTools/mitkClippingPlaneDeformationTool.cpp @@ -1,66 +1,81 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkClippingPlaneDeformationTool.h" #include "mitkClippingPlaneDeformationTool.xpm" #include "mitkBaseRenderer.h" #include "mitkGlobalInteraction.h" #include "mitkRenderingManager.h" #include "mitkToolManager.h" namespace mitk{ MITK_TOOL_MACRO(ClippingTools_EXPORT, ClippingPlaneDeformationTool, "Clipping Tool Deformation"); } mitk::ClippingPlaneDeformationTool::ClippingPlaneDeformationTool() : Tool( "global" ) { } mitk::ClippingPlaneDeformationTool::~ClippingPlaneDeformationTool() { } const char** mitk::ClippingPlaneDeformationTool::GetXPM() const { return mitkClippingPlaneDeformationTool_xpm; } const char* mitk::ClippingPlaneDeformationTool::GetName() const { return "Deformation"; } const char* mitk::ClippingPlaneDeformationTool::GetGroup() const { return "ClippingTool"; } void mitk::ClippingPlaneDeformationTool::Activated() { Superclass::Activated(); //check if the Clipping plane is changed. if(m_ClippingPlaneNode != m_ToolManager->GetWorkingData(0)) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_SurfaceInteractor); this->ClippingPlaneChanged(); } mitk::GlobalInteraction::GetInstance()->AddInteractor(m_SurfaceInteractor); } void mitk::ClippingPlaneDeformationTool::Deactivated() { Superclass::Deactivated(); mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_SurfaceInteractor); } //Checks the working data node, if it has an interactor. Otherwise initial a new one. void mitk::ClippingPlaneDeformationTool::ClippingPlaneChanged() { m_ClippingPlaneNode = m_ToolManager->GetWorkingData(0); m_SurfaceInteractor = dynamic_cast(m_ClippingPlaneNode->GetInteractor()); if (m_SurfaceInteractor.IsNull()) m_SurfaceInteractor = mitk::SurfaceDeformationInteractor3D::New("AffineInteractor3D", m_ClippingPlaneNode); } \ No newline at end of file diff --git a/Modules/ClippingTools/mitkClippingPlaneRotationTool.cpp b/Modules/ClippingTools/mitkClippingPlaneRotationTool.cpp index 4e7c6b18e4..3515960098 100644 --- a/Modules/ClippingTools/mitkClippingPlaneRotationTool.cpp +++ b/Modules/ClippingTools/mitkClippingPlaneRotationTool.cpp @@ -1,69 +1,84 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkClippingPlaneRotationTool.h" #include "mitkClippingPlaneRotationTool.xpm" #include "mitkBaseRenderer.h" #include "mitkGlobalInteraction.h" #include "mitkRenderingManager.h" #include "mitkToolManager.h" namespace mitk { MITK_TOOL_MACRO(ClippingTools_EXPORT, ClippingPlaneRotationTool, "Clipping Tool Rotation"); } mitk::ClippingPlaneRotationTool::ClippingPlaneRotationTool() : Tool( "global" ) { } mitk::ClippingPlaneRotationTool::~ClippingPlaneRotationTool() { } const char** mitk::ClippingPlaneRotationTool::GetXPM() const { return mitkClippingPlaneRotationTool_xpm; } const char* mitk::ClippingPlaneRotationTool::GetName() const { return "Rotation"; } const char* mitk::ClippingPlaneRotationTool::GetGroup() const { return "ClippingTool"; } void mitk::ClippingPlaneRotationTool::Activated() { Superclass::Activated(); //check if the Clipping plane is changed. if(m_ClippingPlaneNode != m_ToolManager->GetWorkingData(0)) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_AffineInteractor); this->ClippingPlaneChanged(); } m_AffineInteractor->SetInteractionModeToRotation(); mitk::GlobalInteraction::GetInstance()->AddInteractor(m_AffineInteractor); } void mitk::ClippingPlaneRotationTool::Deactivated() { Superclass::Deactivated(); mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_AffineInteractor); } //Checks the working data node, if it has an interactor. Otherwise initial a new one. void mitk::ClippingPlaneRotationTool::ClippingPlaneChanged() { m_ClippingPlaneNode = m_ToolManager->GetWorkingData(0); m_AffineInteractor = dynamic_cast(m_ClippingPlaneNode->GetInteractor()); if (m_AffineInteractor.IsNull()) m_AffineInteractor = mitk::AffineInteractor3D::New("AffineInteractor3D", m_ClippingPlaneNode); } \ No newline at end of file diff --git a/Modules/ClippingTools/mitkClippingPlaneTranslationTool.cpp b/Modules/ClippingTools/mitkClippingPlaneTranslationTool.cpp index 829307abbb..33e967c431 100644 --- a/Modules/ClippingTools/mitkClippingPlaneTranslationTool.cpp +++ b/Modules/ClippingTools/mitkClippingPlaneTranslationTool.cpp @@ -1,68 +1,83 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkClippingPlaneTranslationTool.h" #include "mitkClippingPlaneTranslationTool.xpm" #include "mitkBaseRenderer.h" #include "mitkGlobalInteraction.h" #include "mitkRenderingManager.h" #include "mitkToolManager.h" namespace mitk { MITK_TOOL_MACRO(ClippingTools_EXPORT, ClippingPlaneTranslationTool, "Clipping Tool Translation"); } mitk::ClippingPlaneTranslationTool::ClippingPlaneTranslationTool() : Tool( "global" ) { } mitk::ClippingPlaneTranslationTool::~ClippingPlaneTranslationTool() { } const char** mitk::ClippingPlaneTranslationTool::GetXPM() const { return mitkClippingPlaneTranslationTool_xpm; } const char* mitk::ClippingPlaneTranslationTool::GetName() const { return "Translation"; } const char* mitk::ClippingPlaneTranslationTool::GetGroup() const { return "ClippingTool"; } void mitk::ClippingPlaneTranslationTool::Activated() { Superclass::Activated(); //check if the Clipping plane is changed. if(m_ClippingPlaneNode != m_ToolManager->GetWorkingData(0)) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_AffineInteractor); this->ClippingPlaneChanged(); } m_AffineInteractor->SetInteractionModeToTranslation(); mitk::GlobalInteraction::GetInstance()->AddInteractor(m_AffineInteractor); } void mitk::ClippingPlaneTranslationTool::Deactivated() { Superclass::Deactivated(); mitk::GlobalInteraction::GetInstance()->RemoveInteractor(m_AffineInteractor); } //Checks the working data node, if it has an interactor. Otherwise initial a new one. void mitk::ClippingPlaneTranslationTool::ClippingPlaneChanged() { m_ClippingPlaneNode = m_ToolManager->GetWorkingData(0); m_AffineInteractor = dynamic_cast(m_ClippingPlaneNode->GetInteractor()); if (m_AffineInteractor.IsNull()) m_AffineInteractor = mitk::AffineInteractor3D::New("AffineInteractor3D", m_ClippingPlaneNode); } \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/itkDiffusionQballGeneralizedFaImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkDiffusionQballGeneralizedFaImageFilter.txx index 4644fd2a84..e50737504e 100644 --- a/Modules/DiffusionImaging/Algorithms/itkDiffusionQballGeneralizedFaImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkDiffusionQballGeneralizedFaImageFilter.txx @@ -1,207 +1,222 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkDiffusionQballGeneralizedFaImageFilter_txx #define __itkDiffusionQballGeneralizedFaImageFilter_txx #include #include #include #define _USE_MATH_DEFINES #include #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionIterator.h" #include "itkArray.h" #include "vnl/vnl_vector.h" #include "itkOrientationDistributionFunction.h" namespace itk { //#define QBALL_RECON_PI M_PI template< class TOdfPixelType, class TGfaPixelType, int NrOdfDirections> DiffusionQballGeneralizedFaImageFilter< TOdfPixelType, TGfaPixelType, NrOdfDirections> ::DiffusionQballGeneralizedFaImageFilter() : m_ComputationMethod(GFA_STANDARD) { // At least 1 inputs is necessary for a vector image. // For images added one at a time we need at least six this->SetNumberOfRequiredInputs( 1 ); } template< class TOdfPixelType, class TGfaPixelType, int NrOdfDirections> void DiffusionQballGeneralizedFaImageFilter< TOdfPixelType, TGfaPixelType, NrOdfDirections> ::BeforeThreadedGenerateData() { } template< class TOdfPixelType, class TGfaPixelType, int NrOdfDirections> void DiffusionQballGeneralizedFaImageFilter< TOdfPixelType, TGfaPixelType, NrOdfDirections> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int ) { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); oit.GoToBegin(); typedef itk::OrientationDistributionFunction OdfType; typedef ImageRegionConstIterator< InputImageType > InputIteratorType; typedef typename InputImageType::PixelType OdfVectorType; typename InputImageType::Pointer inputImagePointer = NULL; inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); InputIteratorType git(inputImagePointer, outputRegionForThread ); git.GoToBegin(); while( !git.IsAtEnd() ) { OdfVectorType b = git.Get(); TGfaPixelType outval = -1; switch( m_ComputationMethod ) { case GFA_STANDARD: { OdfType odf = b.GetDataPointer(); outval = odf.GetGeneralizedFractionalAnisotropy(); break; } case GFA_QUANTILES_HIGH_LOW: { vnl_vector_fixed sorted; for(int i=0; i sorted; for(int i=0; i sorted; for(int i=0; i sorted; for(int i=0; i void DiffusionQballGeneralizedFaImageFilter< TOdfPixelType, TGfaPixelType, NrOdfDirections> ::PrintSelf(std::ostream& os, Indent indent) const { Superclass::PrintSelf(os,indent); } } #endif // __itkDiffusionQballGeneralizedFaImageFilter_txx diff --git a/Modules/DiffusionImaging/Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.cpp index 77ef3a5dff..2ba9352dd6 100644 --- a/Modules/DiffusionImaging/Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.cpp @@ -1,171 +1,186 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkDiffusionQballPrepareVisualizationImageFilter_cpp #define __itkDiffusionQballPrepareVisualizationImageFilter_cpp #include #include #include #include "itkDiffusionQballPrepareVisualizationImageFilter.h" #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionIterator.h" #include "itkArray.h" #include "vnl/vnl_vector.h" #include "itkOrientationDistributionFunction.h" #define _USE_MATH_DEFINES #include namespace itk { //#define QBALL_RECON_PI M_PI template< class TOdfPixelType, int NrOdfDirections> DiffusionQballPrepareVisualizationImageFilter< TOdfPixelType, NrOdfDirections> ::DiffusionQballPrepareVisualizationImageFilter() : m_Threshold(0), m_ScaleByGfaType(GfaFilterType::GFA_STANDARD), m_DoScaleGfa(false), m_GfaParam1(2), m_GfaParam2(1) { // At least 1 inputs is necessary for a vector image. // For images added one at a time we need at least six this->SetNumberOfRequiredInputs( 1 ); } template< class TOdfPixelType, int NrOdfDirections> void DiffusionQballPrepareVisualizationImageFilter< TOdfPixelType, NrOdfDirections> ::BeforeThreadedGenerateData() { if( m_NormalizationMethod == PV_GLOBAL_MAX ) { typename InputImageType::Pointer inputImagePointer = NULL; inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typename GfaFilterType::Pointer filter = GfaFilterType::New(); filter->SetInput(inputImagePointer); filter->SetNumberOfThreads(4); filter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE); filter->Update(); typedef typename itk::MinimumMaximumImageCalculator< typename GfaFilterType::OutputImageType > MaxFilterType; typename MaxFilterType::Pointer maxFilter = MaxFilterType::New(); maxFilter->SetImage(filter->GetOutput()); maxFilter->ComputeMaximum(); m_GlobalInputMaximum = maxFilter->GetMaximum(); } //if(m_DoScaleGfa) { typename InputImageType::Pointer inputImagePointer = NULL; inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typename GfaFilterType::Pointer filter = GfaFilterType::New(); filter->SetInput(inputImagePointer); filter->SetNumberOfThreads(4); filter->SetComputationMethod(m_ScaleByGfaType); filter->SetParam1(m_GfaParam1); filter->SetParam2(m_GfaParam2); filter->Update(); m_GfaImage = filter->GetOutput(); } } template< class TOdfPixelType, int NrOdfDirections> void DiffusionQballPrepareVisualizationImageFilter< TOdfPixelType, NrOdfDirections> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int ) { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); oit.GoToBegin(); typedef itk::OrientationDistributionFunction OdfType; typedef ImageRegionConstIterator< InputImageType > InputIteratorType; typedef typename InputImageType::PixelType OdfVectorType; typename InputImageType::Pointer inputImagePointer = NULL; inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); InputIteratorType git(inputImagePointer, outputRegionForThread ); git.GoToBegin(); typedef ImageRegionConstIterator< GfaImageType > GfaIteratorType; GfaIteratorType gfaIt(m_GfaImage, outputRegionForThread); while( !git.IsAtEnd() ) { OdfVectorType b = git.Get(); OdfType odf = b.GetDataPointer(); switch( m_NormalizationMethod ) { case PV_NONE: { break; } case PV_MAX: { odf = odf.MaxNormalize(); break; } case PV_MIN_MAX: { odf = odf.MinMaxNormalize(); break; } case PV_GLOBAL_MAX: { odf *= 1.0/m_GlobalInputMaximum; break; } case PV_MIN_MAX_INVERT: { odf = odf.MinMaxNormalize(); for(int i=0; i void DiffusionQballPrepareVisualizationImageFilter< TOdfPixelType, NrOdfDirections> ::PrintSelf(std::ostream& os, Indent indent) const { Superclass::PrintSelf(os,indent); os << indent << "m_Threshold: " << m_Threshold << std::endl; } } #endif // __itkDiffusionQballPrepareVisualizationImageFilter_cpp diff --git a/Modules/DiffusionImaging/Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.txx index 6e1015e6fa..22e630c103 100644 --- a/Modules/DiffusionImaging/Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.txx @@ -1,121 +1,136 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkDiffusionTensorPrincipleDirectionImageFilter_txx #define __itkDiffusionTensorPrincipleDirectionImageFilter_txx #include #include #include //#include "itkDiffusionTensorPrincipleDirectionImageFilter.h" #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionIterator.h" #include "itkArray.h" #include "vnl/vnl_vector.h" #define _USE_MATH_DEFINES #include namespace itk { //#define QBALL_RECON_PI M_PI template< class TTensorPixelType, class TPDPixelType> DiffusionTensorPrincipleDirectionImageFilter< TTensorPixelType, TPDPixelType> ::DiffusionTensorPrincipleDirectionImageFilter() { // At least 1 inputs is necessary for a vector image. // For images added one at a time we need at least six this->SetNumberOfRequiredInputs( 1 ); } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipleDirectionImageFilter< TTensorPixelType, TPDPixelType> ::BeforeThreadedGenerateData() { } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipleDirectionImageFilter< TTensorPixelType, TPDPixelType> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int ) { typedef itk::DiffusionTensor3D TensorType; typedef ImageRegionConstIterator< InputImageType > InputIteratorType; typedef typename InputImageType::PixelType InputTensorType; typename InputImageType::Pointer inputImagePointer = NULL; inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); outputImage->SetSpacing( inputImagePointer->GetSpacing() ); // Set the image spacing outputImage->SetOrigin( inputImagePointer->GetOrigin() ); // Set the image origin outputImage->SetDirection( inputImagePointer->GetDirection() ); // Set the image direction outputImage->SetRegions( inputImagePointer->GetLargestPossibleRegion() ); outputImage->Allocate(); ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); oit.GoToBegin(); InputIteratorType git(inputImagePointer, outputRegionForThread ); git.GoToBegin(); while( !git.IsAtEnd() ) { InputTensorType b = git.Get(); TensorType tensor = b.GetDataPointer(); typename OutputImageType::PixelType dir; typename TensorType::EigenValuesArrayType eigenvalues; typename TensorType::EigenVectorsMatrixType eigenvectors; if(tensor.GetTrace()!=0) { tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors); // int index = 2; // if( (eigenvalues[0] >= eigenvalues[1]) // && (eigenvalues[0] >= eigenvalues[2]) ) // index = 0; // else if(eigenvalues[1] >= eigenvalues[2]) // index = 1; vnl_vector_fixed vec; vec[0] = eigenvectors(/*index*/2,0); vec[1] = eigenvectors(/*index*/2,1); vec[2] = eigenvectors(/*index*/2,2); dir[0] = (TPDPixelType)vec[0]; dir[1] = (TPDPixelType)vec[1]; dir[2] = (TPDPixelType)vec[2]; } else { dir[0] = (TPDPixelType)0; dir[1] = (TPDPixelType)0; dir[2] = (TPDPixelType)0; } oit.Set( dir ); ++oit; ++git; // Gradient image iterator } std::cout << "One Thread finished extraction" << std::endl; } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipleDirectionImageFilter< TTensorPixelType, TPDPixelType> ::PrintSelf(std::ostream& os, Indent indent) const { } } #endif // __itkDiffusionQballPrincipleDirectionsImageFilter_txx diff --git a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp index 8461b0afd6..7873cae9e6 100644 --- a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp @@ -1,156 +1,171 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkExtractChannelFromRgbaImageFilter.h" // VTK #include #include #include // misc #include namespace itk{ template< class ReferenceImageType, class OutputImageType > ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::ExtractChannelFromRgbaImageFilter(): m_Channel(RED) { } template< class ReferenceImageType, class OutputImageType > ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::~ExtractChannelFromRgbaImageFilter() { } template< class ReferenceImageType, class OutputImageType > void ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::GenerateData() { typename InputImageType::Pointer rgbaImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); typename InputImageType::RegionType region = rgbaImage->GetLargestPossibleRegion(); outputImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing outputImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin outputImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction outputImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion()); outputImage->Allocate(); outputImage->FillBuffer(0); float* outImageBufferPointer = outputImage->GetBufferPointer(); itk::Image< short, 3 >::Pointer counterImage = itk::Image< short, 3 >::New(); counterImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing counterImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin counterImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction counterImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion()); counterImage->Allocate(); counterImage->FillBuffer(0); short* counterImageBufferPointer = counterImage->GetBufferPointer(); int w = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(0); int h = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(1); int d = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(2); typedef ImageRegionConstIterator< InputImageType > InImageIteratorType; InImageIteratorType rgbaIt(rgbaImage, region); rgbaIt.GoToBegin(); while(!rgbaIt.IsAtEnd()){ InPixelType x = rgbaIt.Get(); ++rgbaIt; itk::Point vertex; itk::Index<3> index = rgbaIt.GetIndex(); rgbaImage->TransformIndexToPhysicalPoint(index, vertex); outputImage->TransformPhysicalPointToIndex(vertex, index); itk::ContinuousIndex contIndex; outputImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; int px = index[0]; if (frac_x<0) { px -= 1; frac_x += 1; } int py = index[1]; if (frac_y<0) { py -= 1; frac_y += 1; } int pz = index[2]; if (frac_z<0) { pz -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (px < 0 || px >= w-1) continue; if (py < 0 || py >= h-1) continue; if (pz < 0 || pz >= d-1) continue; OutPixelType out; switch (m_Channel) { case RED: out = (float)x.GetRed()/255; break; case GREEN: out = (float)x.GetGreen()/255; break; case BLUE: out = (float)x.GetBlue()/255; break; case ALPHA: out = (float)x.GetAlpha()/255; } outImageBufferPointer[( px + w*(py + h*pz ))] += out*( frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz ))] += out*( frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px + w*(py + h*pz+h))] += out*( frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz+h))] += out*( frac_x)*(1-frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz ))] += out*(1-frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz+h))] += out*(1-frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += out*(1-frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += out*(1-frac_x)*(1-frac_y)*(1-frac_z); counterImageBufferPointer[( px + w*(py + h*pz ))] += 1; counterImageBufferPointer[( px + w*(py+1+ h*pz ))] += 1; counterImageBufferPointer[( px + w*(py + h*pz+h))] += 1; counterImageBufferPointer[( px + w*(py+1+ h*pz+h))] += 1; counterImageBufferPointer[( px+1 + w*(py + h*pz ))] += 1; counterImageBufferPointer[( px+1 + w*(py + h*pz+h))] += 1; counterImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += 1; counterImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += 1; } typedef ImageRegionIterator< OutputImageType > OutImageIteratorType; OutImageIteratorType outIt(outputImage, outputImage->GetLargestPossibleRegion()); outIt.GoToBegin(); typedef ImageRegionConstIterator< itk::Image< short, 3 > > CountImageIteratorType; CountImageIteratorType counterIt(counterImage, counterImage->GetLargestPossibleRegion()); counterIt.GoToBegin(); while(!outIt.IsAtEnd() && !counterIt.IsAtEnd()){ if (counterIt.Value()>0) outIt.Set(outIt.Value()/counterIt.Value()); ++outIt; ++counterIt; } } } diff --git a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h index 571b6d8760..e8379ab84c 100644 --- a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h @@ -1,57 +1,72 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkExtractChannelFromRgbaImageFilter_h__ #define __itkExtractChannelFromRgbaImageFilter_h__ #include #include #include #include namespace itk{ template< class ReferenceImageType, class OutputImageType > class ExtractChannelFromRgbaImageFilter : public ImageToImageFilter< itk::Image,3>, OutputImageType > { public: enum Channel { RED, GREEN, BLUE, ALPHA }; typedef ExtractChannelFromRgbaImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef itk::Image,3> InputImageType; typedef typename OutputImageType::PixelType OutPixelType; typedef typename InputImageType::PixelType InPixelType; itkNewMacro(Self); itkTypeMacro( ExtractChannelFromRgbaImageFilter, ImageSource ); /** Upsampling factor **/ void GenerateData(); itkSetMacro(Channel, Channel) itkSetMacro(ReferenceImage, typename ReferenceImageType::Pointer) protected: ExtractChannelFromRgbaImageFilter(); virtual ~ExtractChannelFromRgbaImageFilter(); Channel m_Channel; typename ReferenceImageType::Pointer m_ReferenceImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkExtractChannelFromRgbaImageFilter.cpp" #endif #endif // __itkExtractChannelFromRgbaImageFilter_h__ diff --git a/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.h b/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.h index b299885521..a9a59749c7 100644 --- a/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.h @@ -1,101 +1,116 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkReduceDirectionGradientsFilter.h $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_ReduceDirectionGradientsFilter_h_ #define _itk_ReduceDirectionGradientsFilter_h_ #include #include #include namespace itk { template class ReduceDirectionGradientsFilter : public ImageToImageFilter, itk::VectorImage > { public: typedef ReduceDirectionGradientsFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< itk::VectorImage, itk::VectorImage > Superclass; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Runtime information support. */ itkTypeMacro(ReduceDirectionGradientsFilter, ImageToImageFilter); typedef TInputScalarType InputScalarType; typedef itk::VectorImage InputImageType; typedef typename InputImageType::PixelType InputPixelType; typedef TOutputScalarType OutputScalarType; typedef itk::VectorImage OutputImageType; typedef typename OutputImageType::PixelType OutputPixelType; typedef OutputScalarType BaselineScalarType; typedef BaselineScalarType BaselinePixelType; typedef typename itk::Image BaselineImageType; typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; itkGetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer) itkSetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer) itkGetMacro(GradientDirections, GradientDirectionContainerType::Pointer) itkSetMacro(GradientDirections, GradientDirectionContainerType::Pointer) itkGetMacro(NumGradientDirections, int) itkSetMacro(NumGradientDirections, int) itkGetMacro(Iterations, unsigned long) itkSetMacro(Iterations, unsigned long) std::vector< int > GetUsedGradientIndices(); protected: ReduceDirectionGradientsFilter(); ~ReduceDirectionGradientsFilter() {}; void GenerateData(); double Costs(); GradientDirectionContainerType::Pointer m_GradientDirections; GradientDirectionContainerType::Pointer m_OriginalGradientDirections; std::vector< int > m_UsedGradientIndices; std::vector< int > m_UnUsedGradientIndices; std::vector< int > m_BaselineImageIndices; int m_NumGradientDirections; unsigned long m_Iterations; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkReduceDirectionGradientsFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.txx b/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.txx index 4aba95fa5b..630f5c6e97 100644 --- a/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkReduceDirectionGradientsFilter.txx @@ -1,192 +1,207 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkReduceDirectionGradientsFilter.txx $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_ReduceDirectionGradientsFilter_txx_ #define _itk_ReduceDirectionGradientsFilter_txx_ #endif #define _USE_MATH_DEFINES #include "itkReduceDirectionGradientsFilter.h" #include #include #include #include namespace itk { template ReduceDirectionGradientsFilter ::ReduceDirectionGradientsFilter(): m_Iterations(100000) { this->SetNumberOfRequiredInputs( 1 ); } template double ReduceDirectionGradientsFilter ::Costs() { double costs = 0; int c=0; for (std::vector::iterator it = m_UsedGradientIndices.begin(); it!=m_UsedGradientIndices.end(); ++it) { for (std::vector::iterator it2 = m_UsedGradientIndices.begin()+c; it2!=m_UsedGradientIndices.end(); ++it2) if (*it!=*it2) { vnl_vector_fixed v1 = m_OriginalGradientDirections->at(*it); vnl_vector_fixed v2 = m_OriginalGradientDirections->at(*it2); v1.normalize(); v2.normalize(); double angle = acos(dot_product(v1,v2)); if (angle>0) costs += 1/angle; } c++; } return costs; } template void ReduceDirectionGradientsFilter ::GenerateData() { srand(time(NULL)); // initialize index vectors m_UsedGradientIndices.clear(); m_UnUsedGradientIndices.clear(); if ( m_OriginalGradientDirections->Size()<= m_NumGradientDirections ) m_NumGradientDirections = m_OriginalGradientDirections->Size(); int c=0; int numB0 = 0; for (int i=0; iSize(); i++) { vnl_vector_fixed< double, 3 > v = m_OriginalGradientDirections->at(i); v.normalize(); if (fabs(v[0])>0.001 || fabs(v[1])>0.001 || fabs(v[2])>0.001) { if (cSize(); for (unsigned long i=0; iSetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion()); outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->SetVectorLength(m_NumGradientDirections+numB0); outImage->Allocate(); itk::ImageRegionIterator< OutputImageType > newIt(outImage, outImage->GetLargestPossibleRegion()); newIt.GoToBegin(); typename InputImageType::Pointer inImage = const_cast(this->GetInput(0)); itk::ImageRegionIterator< InputImageType > oldIt(inImage, inImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel OutputPixelType newVec; newVec.SetSize(m_NumGradientDirections+numB0); newVec.AllocateElements(m_NumGradientDirections+numB0); int ind1 = -1; while(!newIt.IsAtEnd()) { // progress typename OutputImageType::IndexType ind = newIt.GetIndex(); ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates InputPixelType oldVec = oldIt.Get(); for(int i=0; iInsertElement(i, m_OriginalGradientDirections->at(m_BaselineImageIndices.at(i))); for(int i=0; iInsertElement(i+numB0, m_OriginalGradientDirections->at(m_UsedGradientIndices.at(i))); this->SetNumberOfRequiredOutputs (1); this->SetNthOutput (0, outImage); } template std::vector< int > ReduceDirectionGradientsFilter ::GetUsedGradientIndices() { return m_UsedGradientIndices; } } // end of namespace diff --git a/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.h index d9f3f3c36e..0b70e01eca 100644 --- a/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.h @@ -1,161 +1,176 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.h $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_ResidualImageFilter_h_ #define _itk_ResidualImageFilter_h_ #include "itkImageToImageFilter.h" #include namespace itk { template class ResidualImageFilter : public ImageToImageFilter, itk::Image > { public: typedef TInputScalarType InputScalarType; typedef itk::VectorImage InputImageType; typedef typename InputImageType::PixelType InputPixelType; typedef typename InputImageType::RegionType InputImageRegionType; typedef TOutputScalarType OutputScalarType; typedef itk::Image OutputImageType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef ResidualImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; typedef itk::Image BaselineImageType; itkTypeMacro (ResidualImageFilter, ImageToImageFilter); itkStaticConstMacro (ImageDimension, unsigned int, OutputImageType::ImageDimension); itkNewMacro (Self); void SetSecondDiffusionImage(typename InputImageType::Pointer diffImage) { m_SecondDiffusionImage = diffImage; } std::vector GetQ1() { return m_Q1; } std::vector GetQ3() { return m_Q3; } std::vector GetMeans() { return m_Means; } std::vector GetPercentagesOfOutliers() { return m_PercentagesOfOutliers; } std::vector< std::vector > GetOutliersPerSlice() { return m_OutliersPerSlice; } void SetGradients(GradientDirectionContainerType* grads) { m_Gradients = grads; } void SetBaseLineImage(BaselineImageType* baseline) { m_BaseLineImage = baseline; } void SetB0Threshold(InputScalarType threshold) { m_B0Threshold = threshold; } itkSetMacro(B0Index, int) protected: ResidualImageFilter() { m_B0Threshold = 30.0; // default value. allow user to redefine }; ~ResidualImageFilter(){}; void PrintSelf (std::ostream& os, Indent indent) const { Superclass::PrintSelf (os, indent); } void GenerateData(); private: ResidualImageFilter (const Self&); void operator=(const Self&); typename InputImageType::Pointer m_SecondDiffusionImage; std::vector m_Means, m_Q1, m_Q3, m_PercentagesOfOutliers; // 'Outer' vector: slices, 'Inner' volumes std::vector< std::vector > m_OutliersPerSlice; GradientDirectionContainerType* m_Gradients; typename BaselineImageType::Pointer m_BaseLineImage; InputScalarType m_B0Threshold; int m_B0Index; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkResidualImageFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.txx index 19c0a5646e..f3f99627c7 100644 --- a/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkResidualImageFilter.txx @@ -1,274 +1,289 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_ResidualImageFilter_txx_ #define _itk_ResidualImageFilter_txx_ #endif #include "itkResidualImageFilter.h" #include #include namespace itk { template void ResidualImageFilter ::GenerateData() { typename InputImageType::SizeType size = this->GetInput()->GetLargestPossibleRegion().GetSize(); typename InputImageType::SizeType size2 = m_SecondDiffusionImage->GetLargestPossibleRegion().GetSize(); if(size != size2) { MITK_ERROR << "Sizes do not match"; return; } // Initialize output image typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); outputImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing outputImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin outputImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction outputImage->SetRegions( this->GetInput()->GetLargestPossibleRegion() ); outputImage->Allocate(); outputImage->FillBuffer(0.0); std::vector< std::vector > residuals; // per slice, per volume std::vector< std::vector > > residualsPerSlice; // Detrmine number of B0 images int numberB0=0; for(int i=0; iSize(); i++) { GradientDirectionType grad = m_Gradients->ElementAt(i); if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001) { numberB0++; } } residuals.resize(this->GetInput()->GetVectorLength()-numberB0); // Calculate the standard residual image and for each volume put all residuals in a vector for(int z=0; z > sliceResiduals; // residuals per volume for this slice sliceResiduals.resize(this->GetInput()->GetVectorLength()-numberB0); for(int y=0; y ix; ix[0] = x; ix[1] = y; ix[2] = z; typename InputImageType::PixelType p1 = this->GetInput()->GetPixel(ix); typename InputImageType::PixelType p2 = m_SecondDiffusionImage->GetPixel(ix); int s1 = p1.GetSize(); int s2 = p2.GetSize(); if(p1.GetSize() != p2.GetSize()) { MITK_ERROR << "Vector sizes do not match"; return; } if(p1.GetElement(m_B0Index) <= m_B0Threshold) { continue; } double res = 0; int shift = 0; // correction for the skipped B0 images for(int i = 0; iElementAt(i); if(!(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001)) { double val1 = (double)p1.GetElement(i); double val2 = (double)p2.GetElement(i); res += abs(val1-val2); residuals[i-shift].push_back(val1-val2); sliceResiduals[i-shift].push_back(val1-val2); } else { shift++; } } res = res/p1.GetSize(); outputImage->SetPixel(ix, res); } } residualsPerSlice.push_back(sliceResiduals); } // for each dw volume: sort the the measured residuals (for each voxel) to enable determining Q1 and Q3; calculate means // determine percentage of errors as described in QUALITY ASSESSMENT THROUGH ANALYSIS OF RESIDUALS OF DIFFUSION IMAGE FITTING // Leemans et al 2008 double q1,q3, median; std::vector< std::vector >::iterator it = residuals.begin(); while(it != residuals.end()) { std::vector res = *it; // sort std::sort(res.begin(), res.end()); q1 = res[0.25*res.size()]; m_Q1.push_back(q1); q3 = res[0.75*res.size()]; m_Q3.push_back(q3); median = res[0.5*res.size()]; double iqr = q3-q1; double outlierThreshold = median + 1.5*iqr; double numberOfOutliers = 0.0; std::vector::iterator resIt = res.begin(); double mean = 0; while(resIt != res.end()) { double f = *resIt; if(f>outlierThreshold) { numberOfOutliers++; } mean += f; ++resIt; } double percOfOutliers = 100 * numberOfOutliers / res.size(); m_PercentagesOfOutliers.push_back(percOfOutliers); mean /= res.size(); m_Means.push_back(mean); ++it; } // Calculate for each slice the number of outliers per volume(dw volume) std::vector< std::vector > >::iterator sliceIt = residualsPerSlice.begin(); while(sliceIt != residualsPerSlice.end()) { std::vector< std::vector > currentSlice = *sliceIt; std::vector percentages; std::vector< std::vector >::iterator volIt = currentSlice.begin(); while(volIt != currentSlice.end()) { std::vector currentVolume = *volIt; //sort std::sort(currentVolume.begin(), currentVolume.end()); q1 = currentVolume[0.25*currentVolume.size()]; q3 = currentVolume[0.75*currentVolume.size()]; median = currentVolume[0.5*currentVolume.size()]; double iqr = q3-q1; double outlierThreshold = median + 1.5*iqr; double numberOfOutliers = 0.0; std::vector::iterator resIt = currentVolume.begin(); double mean; while(resIt != currentVolume.end()) { double f = *resIt; if(f>outlierThreshold) { numberOfOutliers++; } mean += f; ++resIt; } double percOfOutliers = 100 * numberOfOutliers / currentVolume.size(); percentages.push_back(percOfOutliers); ++volIt; } m_OutliersPerSlice.push_back(percentages); ++sliceIt; } } } // end of namespace diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorDerivedMeasurementsFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorDerivedMeasurementsFilter.txx index 19dd22cd8a..e391fb649f 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorDerivedMeasurementsFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkTensorDerivedMeasurementsFilter.txx @@ -1,130 +1,145 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkTensorDerivedMeasurementsFilter_txx #define __itkTensorDerivedMeasurementsFilter_txx namespace itk { template TensorDerivedMeasurementsFilter::TensorDerivedMeasurementsFilter() : m_Measure(AD) { } template void TensorDerivedMeasurementsFilter::GenerateData() { typename TensorImageType::Pointer tensorImage = static_cast< TensorImageType * >( this->ProcessObject::GetInput(0) ); typedef ImageRegionConstIterator< TensorImageType > TensorImageIteratorType; typedef ImageRegionIterator< OutputImageType > OutputImageIteratorType; typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); typename TensorImageType::RegionType region = tensorImage->GetLargestPossibleRegion(); outputImage->SetSpacing( tensorImage->GetSpacing() ); // Set the image spacing outputImage->SetOrigin( tensorImage->GetOrigin() ); // Set the image origin outputImage->SetDirection( tensorImage->GetDirection() ); // Set the image direction outputImage->SetRegions( tensorImage->GetLargestPossibleRegion()); outputImage->Allocate(); TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetLargestPossibleRegion()); OutputImageIteratorType outputIt(outputImage, outputImage->GetLargestPossibleRegion()); tensorIt.GoToBegin(); outputIt.GoToBegin(); while(!tensorIt.IsAtEnd() && !outputIt.IsAtEnd()){ TensorType tensor = tensorIt.Get(); switch(m_Measure) { case FA: { TPixel diffusionIndex = tensor.GetFractionalAnisotropy(); outputIt.Set(diffusionIndex); break; } case RA: { TPixel diffusionIndex = tensor.GetRelativeAnisotropy(); outputIt.Set(diffusionIndex); break; } case AD: { // eigenvalues are sorted in ascending order by default because the // itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); outputIt.Set(evs[2]); break; } case RD: { // eigenvalues are sorted in ascending order by default because the // itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); outputIt.Set((evs[0]+evs[1])/2.0); break; } case CA: { // eigenvalues are sorted in ascending order by default because the // itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); if (evs[2] == 0) { outputIt.Set(0); break; } outputIt.Set(1.0-(evs[0]+evs[1])/(2.0*evs[2])); break; } case L2: { // eigenvalues are sorted in ascending order by default because the // itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); outputIt.Set(evs[1]); break; } case L3: { // eigenvalues are sorted in ascending order by default because the // itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); outputIt.Set(evs[0]); break; } case MD: { typename TensorType::EigenValuesArrayType evs; tensor.ComputeEigenValues(evs); outputIt.Set((evs[0]+evs[0]+evs[0])/3.0); break; } } ++tensorIt; ++outputIt; } } } #endif // __itkTensorDerivedMeasurements_txx diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.h index 8f1aaabe36..d6c8a64ebd 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.h @@ -1,128 +1,143 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.h $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorImageToDiffusionImageFilter_h_ #define _itk_TensorImageToDiffusionImageFilter_h_ #include "itkImageToImageFilter.h" #include namespace itk { template class TensorImageToDiffusionImageFilter : public ImageToImageFilter,3>, itk::VectorImage > { public: typedef TInputScalarType InputScalarType; typedef itk::DiffusionTensor3D InputPixelType; typedef itk::Image InputImageType; typedef typename InputImageType::RegionType InputImageRegionType; typedef TOutputScalarType OutputScalarType; typedef itk::VectorImage OutputImageType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef OutputScalarType BaselineScalarType; typedef BaselineScalarType BaselinePixelType; typedef typename itk::Image BaselineImageType; typedef typename BaselineImageType::RegionType BaselineImageRegionType; typedef TensorImageToDiffusionImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; itkTypeMacro (TensorImageToDiffusionImageFilter, ImageToImageFilter); itkStaticConstMacro (ImageDimension, unsigned int, OutputImageType::ImageDimension); itkNewMacro (Self); typedef Vector GradientType; typedef std::vector GradientListType; /** Manually Set/Get a list of gradients */ void SetGradientList(const GradientListType list) { m_GradientList = list; this->Modified(); } GradientListType GetGradientList(void) const {return m_GradientList;} void SetBValue( const double& bval) { m_BValue = bval; } itkSetMacro(Min, OutputScalarType); itkSetMacro(Max, OutputScalarType); protected: TensorImageToDiffusionImageFilter() { m_BValue = 1.0; m_BaselineImage = 0; m_Min = 0.0; m_Max = 10000.0; }; ~TensorImageToDiffusionImageFilter(){}; void PrintSelf (std::ostream& os, Indent indent) const { Superclass::PrintSelf (os, indent); } void BeforeThreadedGenerateData( void ); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, int); //void GenerateData(); private: TensorImageToDiffusionImageFilter (const Self&); void operator=(const Self&); GradientListType m_GradientList; double m_BValue; typename BaselineImageType::Pointer m_BaselineImage; OutputScalarType m_Min; OutputScalarType m_Max; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkTensorImageToDiffusionImageFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx index 19ef4242ed..5d7849caf8 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx @@ -1,214 +1,229 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= 2 3 Program: Tensor ToolKit - TTK 4 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $ 5 Language: C++ 6 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ 7 Version: $Revision: 68 $ 8 9 Copyright (c) INRIA 2010. All rights reserved. 10 See LICENSE.txt for details. 11 12 This software is distributed WITHOUT ANY WARRANTY; without even 13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 14 PURPOSE. See the above copyright notices for more information. 15 16 =========================================================================*/ #ifndef _itk_TensorImageToDiffusionImageFilter_txx_ #define _itk_TensorImageToDiffusionImageFilter_txx_ #endif #include "itkTensorImageToDiffusionImageFilter.h" #include "itkTensorToL2NormImageFilter.h" #include "itkRescaleIntensityImageFilter.h" #include #include namespace itk { //template //void // TensorImageToDiffusionImageFilter // ::GenerateData() //{ // // Call a method that can be overriden by a subclass to allocate // // memory for the filter's outputs // this->AllocateOutputs(); // // Call a method that can be overridden by a subclass to perform // // some calculations prior to splitting the main computations into // // separate threads // this->BeforeThreadedGenerateData(); // // Set up the multithreaded processing // ThreadStruct str; // str.Filter = this; // this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads()); // this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str); // // multithread the execution // this->GetMultiThreader()->SingleMethodExecute(); // // Call a method that can be overridden by a subclass to perform // // some calculations after all the threads have completed // this->AfterThreadedGenerateData(); //} template void TensorImageToDiffusionImageFilter ::BeforeThreadedGenerateData() { if( m_GradientList.size()==0 ) { throw itk::ExceptionObject (__FILE__,__LINE__,"Error: gradient list is empty, cannot generate DWI."); } // create a B0 image by taking the norm of the tensor field * scale: typedef itk::TensorToL2NormImageFilter > TensorToL2NormFilterType; typename TensorToL2NormFilterType::Pointer myFilter1 = TensorToL2NormFilterType::New(); myFilter1->SetInput (this->GetInput()); try { myFilter1->Update(); } catch (itk::ExceptionObject &e) { std::cerr << e; return; } typename itk::RescaleIntensityImageFilter< itk::Image, BaselineImageType>::Pointer rescaler= itk::RescaleIntensityImageFilter, BaselineImageType>::New(); rescaler->SetOutputMinimum ( m_Min ); rescaler->SetOutputMaximum ( m_Max ); rescaler->SetInput ( myFilter1->GetOutput() ); try { rescaler->Update(); } catch (itk::ExceptionObject &e) { std::cerr << e; return; } m_BaselineImage = rescaler->GetOutput(); typename OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion()); outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->SetVectorLength(m_GradientList.size()); outImage->Allocate(); this->SetNumberOfRequiredOutputs (1); this->SetNthOutput (0, outImage); } template void TensorImageToDiffusionImageFilter ::ThreadedGenerateData ( const OutputImageRegionType &outputRegionForThread, int threadId ) { typedef ImageRegionIterator IteratorOutputType; typedef ImageRegionConstIterator IteratorInputType; typedef ImageRegionConstIterator IteratorBaselineType; unsigned long numPixels = outputRegionForThread.GetNumberOfPixels(); unsigned long step = numPixels/100; unsigned long progress = 0; IteratorOutputType itOut (this->GetOutput(0), outputRegionForThread); IteratorInputType itIn (this->GetInput(), outputRegionForThread); IteratorBaselineType itB0 (m_BaselineImage, outputRegionForThread); if( threadId==0 ) { this->UpdateProgress (0.0); } while(!itIn.IsAtEnd()) { if( this->GetAbortGenerateData() ) { throw itk::ProcessAborted(__FILE__,__LINE__); } InputPixelType T = itIn.Get(); BaselinePixelType b0 = itB0.Get(); OutputPixelType out; out.SetSize(m_GradientList.size()); out.Fill(0); if( b0 > 0) { for( unsigned int i=0; i=0) out[i] = static_cast( 1.0*b0*exp ( -1.0 * m_BValue * res ) ); } } out[m_GradientList.size()-1] = b0; itOut.Set(out); if( threadId==0 && step>0) { if( (progress%step)==0 ) { this->UpdateProgress ( double(progress)/double(numPixels) ); } } ++progress; ++itB0; ++itIn; ++itOut; } if( threadId==0 ) { this->UpdateProgress (1.0); } } } // end of namespace diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h index 1e78dd559a..35c80b0b4c 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h @@ -1,92 +1,107 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToQBallImageFilter.h $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorImageToQBallImageFilter_h_ #define _itk_TensorImageToQBallImageFilter_h_ #include "itkImageToImageFilter.h" #include #include namespace itk { template class TensorImageToQBallImageFilter : public ImageToImageFilter,3>, itk::Image,3> > { public: typedef TInputScalarType InputScalarType; typedef itk::DiffusionTensor3D InputPixelType; typedef itk::Image InputImageType; typedef typename InputImageType::RegionType InputImageRegionType; typedef TOutputScalarType OutputScalarType; typedef itk::Vector OutputPixelType; typedef itk::Image OutputImageType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef TensorImageToQBallImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; itkTypeMacro (TensorImageToQBallImageFilter, ImageToImageFilter); itkStaticConstMacro (ImageDimension, unsigned int, OutputImageType::ImageDimension); itkNewMacro (Self); protected: TensorImageToQBallImageFilter(){}; ~TensorImageToQBallImageFilter(){}; void PrintSelf (std::ostream& os, Indent indent) const { Superclass::PrintSelf (os, indent); } void BeforeThreadedGenerateData( void ); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, int); //void GenerateData(); private: TensorImageToQBallImageFilter (const Self&); void operator=(const Self&); typename InputImageType::Pointer m_ItkTensorImage; typename OutputImageType::Pointer m_ItkQBallImage; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkTensorImageToQBallImageFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx index 91f12a6414..8a75d1ab7b 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx @@ -1,116 +1,131 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToQBallImageFilter.txx $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorImageToQBallImageFilter_txx_ #define _itk_TensorImageToQBallImageFilter_txx_ #endif #include "itkTensorImageToQBallImageFilter.h" #include #include #include namespace itk { template void TensorImageToQBallImageFilter ::BeforeThreadedGenerateData() { typename OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion()); outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() ); outImage->Allocate(); outImage->FillBuffer(0.0); this->SetNumberOfRequiredOutputs (1); this->SetNthOutput (0, outImage); } template void TensorImageToQBallImageFilter ::ThreadedGenerateData ( const OutputImageRegionType &outputRegionForThread, int threadId ) { typedef ImageRegionIterator IteratorOutputType; typedef ImageRegionConstIterator IteratorInputType; unsigned long numPixels = outputRegionForThread.GetNumberOfPixels(); unsigned long step = numPixels/100; unsigned long progress = 0; IteratorOutputType itOut (this->GetOutput(0), outputRegionForThread); IteratorInputType itIn (this->GetInput(), outputRegionForThread); if( threadId==0 ) this->UpdateProgress (0.0); while(!itIn.IsAtEnd()) { if( this->GetAbortGenerateData() ) { throw itk::ProcessAborted(__FILE__,__LINE__); } InputPixelType T = itIn.Get(); OutputPixelType out; float tensorelems[6] = { (float)T[0], (float)T[1], (float)T[2], (float)T[3], (float)T[4], (float)T[5], }; itk::DiffusionTensor3D tensor(tensorelems); itk::OrientationDistributionFunction odf; odf.InitFromTensor(tensor); odf.Normalize(); for( unsigned int i=0; i0) { if( (progress%step)==0 ) { this->UpdateProgress ( double(progress)/double(numPixels) ); } } ++progress; ++itIn; ++itOut; } if( threadId==0 ) { this->UpdateProgress (1.0); } MITK_INFO << "one thread finished Q-Ball estimation"; } } // end of namespace diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h b/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h index a167927372..ca4d74d109 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h +++ b/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h @@ -1,238 +1,253 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.h $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorReconstructionWithEigenvalueCorrectionFilter_h_ #define _itk_TensorReconstructionWithEigenvalueCorrectionFilter_h_ #include "itkImageToImageFilter.h" #include #include #include #include #include typedef itk::VectorImage ImageType; namespace itk { template class TensorReconstructionWithEigenvalueCorrectionFilter : public ImageToImageFilter< itk::Image< TDiffusionPixelType, 3 >, itk::Image,3> > { public: typedef TensorReconstructionWithEigenvalueCorrectionFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< Image< TDiffusionPixelType, 3>, Image< DiffusionTensor3D< TTensorPixelType >, 3 > > Superclass; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Runtime information support. */ itkTypeMacro(TensorReconstructionWithEigenvalueCorrectionFilter, ImageToImageFilter); typedef TDiffusionPixelType ReferencePixelType; typedef TDiffusionPixelType GradientPixelType; typedef DiffusionTensor3D< TTensorPixelType > TensorPixelType; /** Reference image data, This image is aquired in the absence * of a diffusion sensitizing field gradient */ typedef typename Superclass::InputImageType ReferenceImageType; typedef Image< TensorPixelType, 3 > TensorImageType; typedef TensorImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; /** Typedef defining one (of the many) gradient images. */ typedef Image< GradientPixelType, 3 > GradientImageType; /** An alternative typedef defining one (of the many) gradient images. * It will be assumed that the vectorImage has the same dimension as the * Reference image and a vector length parameter of \c n (number of * gradient directions) */ typedef VectorImage< GradientPixelType, 3 > GradientImagesType; typedef typename GradientImagesType::PixelType GradientVectorType; /* /** Holds the tensor basis coefficients G_k typedef vnl_matrix_fixed< double, 6, 6 > TensorBasisMatrixType; typedef vnl_matrix< double > CoefficientMatrixType; */ /** Holds each magnetic field gradient used to acquire one DWImage */ typedef vnl_vector_fixed< double, 3 > GradientDirectionType; /** Container to hold gradient directions of the 'n' DW measurements */ typedef VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; /** Another set method to add a gradient directions and its corresponding * image. The image here is a VectorImage. The user is expected to pass the * gradient directions in a container. The ith element of the container * corresponds to the gradient direction of the ith component image the * VectorImage. For the baseline image, a vector of all zeros * should be set. */ void SetGradientImage( GradientDirectionContainerType *, const GradientImagesType *image); /** Set method to set the reference image. */ void SetReferenceImage( ReferenceImageType *referenceImage ) { if( m_GradientImageTypeEnumeration == GradientIsInASingleImage) { itkExceptionMacro( << "Cannot call both methods:" << "AddGradientImage and SetGradientImage. Please call only one of them."); } this->ProcessObject::SetNthInput( 0, referenceImage ); m_GradientImageTypeEnumeration = GradientIsInManyImages; } /** Get reference image */ virtual ReferenceImageType * GetReferenceImage() { return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); } /** Return the gradient direction. idx is 0 based */ virtual GradientDirectionType GetGradientDirection( unsigned int idx) const { if( idx >= m_NumberOfGradientDirections ) { itkExceptionMacro( << "Gradient direction " << idx << "does not exist" ); } return m_GradientDirectionContainer->ElementAt( idx+1 ); } itkSetMacro( BValue, TTensorPixelType); itkSetMacro( B0Threshold, float); itkGetMacro(PseudoInverse, vnl_matrix); itkGetMacro(H, vnl_matrix); itkGetMacro(BVec, vnl_vector); itkGetMacro(B0Mask, vnl_vector); itkGetMacro(Voxdim, vnl_vector); mitk::DiffusionImage::Pointer GetOutputDiffusionImage() { return m_OutputDiffusionImage; } ImageType::Pointer GetVectorImage() { return m_VectorImage; } itk::Image::Pointer GetMask() { return m_MaskImage; } //itkGetMacro(OutputDiffusionImage, mitk::DiffusionImage) //itkGetMacro( GradientDirectionContainer, GradientDirectionContainerType::Pointer); protected: TensorReconstructionWithEigenvalueCorrectionFilter(); ~TensorReconstructionWithEigenvalueCorrectionFilter() {}; void GenerateData(); typedef enum { GradientIsInASingleImage = 1, GradientIsInManyImages, Else } GradientImageTypeEnumeration; private: short CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size); void CalculateAttenuation(vnl_vector org_data, vnl_vector &atten,int nof,int numberb0); void CalculateTensor(vnl_matrix pseudoInverse,vnl_vector atten, vnl_vector &tensor,int nof,int numberb0); /** Gradient image was specified in a single image or in multiple images */ GradientImageTypeEnumeration m_GradientImageTypeEnumeration; /** Number of gradient measurements */ unsigned int m_NumberOfGradientDirections; /** container to hold gradient directions */ GradientDirectionContainerType::Pointer m_GradientDirectionContainer; /** b-value */ TTensorPixelType m_BValue; /** Number of baseline images */ unsigned int m_NumberOfBaselineImages; mitk::DiffusionImage::Pointer m_OutputDiffusionImage; ImageType::Pointer m_VectorImage; float m_B0Threshold; itk::Image::Pointer m_MaskImage; vnl_matrix m_PseudoInverse; vnl_matrix m_H; vnl_vector m_BVec; vnl_vector m_B0Mask; vnl_vector m_Voxdim; typename GradientImagesType::Pointer m_GradientImagePointer; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkTensorReconstructionWithEigenvalueCorrectionFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx index 0695cd4f00..c536d896e7 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx @@ -1,564 +1,579 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorReconstructionWithEigenvalueCorrectionFilter_txx_ #define _itk_TensorReconstructionWithEigenvalueCorrectioFiltern_txx_ #endif #include "itkImageRegionConstIterator.h" #include #include namespace itk { template TensorReconstructionWithEigenvalueCorrectionFilter ::TensorReconstructionWithEigenvalueCorrectionFilter() { m_B0Threshold = 50.0; } template void TensorReconstructionWithEigenvalueCorrectionFilter ::GenerateData ( ) { m_GradientImagePointer = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); typename GradientImagesType::SizeType size = m_GradientImagePointer->GetLargestPossibleRegion().GetSize(); int nof = m_GradientDirectionContainer->Size(); int numberb0=0; int cnt=0; for(int i=0; i vec = m_GradientDirectionContainer->ElementAt(i); if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.0001&& vec[1]>-0.0001 && vec[2]>-0.0001) { numberb0++; } } itk::Vector spacing_term = m_GradientImagePointer->GetSpacing(); itk::Matrix direction_term = m_GradientImagePointer->GetDirection(); vnl_vector spacing_vnl(3); vnl_matrix dir_vnl (3,3); for (int i=0;i<3;i++) { spacing_vnl[i]=spacing_term[i]; for(int j=0;j<3;j++) { dir_vnl[i][j]=direction_term[i][j]; } } vnl_matrix vox_dim_step (3,3); for (int i=0;i<3;i++) { for(int j=0;j<3;j++) { vox_dim_step[i][j]=spacing_vnl[i]*dir_vnl[i][j]; } } vnl_symmetric_eigensystem eigen_spacing(vox_dim_step); vnl_vector vox_dim (3); vox_dim[0]=eigen_spacing.get_eigenvalue(0); vox_dim[1]=eigen_spacing.get_eigenvalue(1); vox_dim[2]=eigen_spacing.get_eigenvalue(2); vox_dim=vox_dim/(vox_dim.min_value()); vnl_matrix directions(nof-numberb0,3); m_B0Mask.set_size(nof); for(int i=0; i vec = m_GradientDirectionContainer->ElementAt(i); if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.001&& vec[1]>-0.001 && vec[2]>-0.001) { m_B0Mask[i]=1; } else { m_B0Mask[i]=0; directions[cnt][0] = vec[0]; directions[cnt][1] = vec[1]; directions[cnt][2] = vec[2]; cnt++; } } vnl_matrix dirsTimesDirsTrans = directions*directions.transpose(); vnl_vector< double> diagonal(nof-numberb0); vnl_vector< double> b_vec(nof-numberb0); vnl_vector< double> temporary(3); for (int i=0;i H(nof-numberb0, 6); vnl_matrix H_org(nof-numberb0, 6); vnl_vector pre_tensor(9); int etbt[6] = { 0, 4, 8, 1, 5, 2 }; for (int i = 0; i < nof-numberb0; i++) { for (int j = 0; j < 3; j++) { temporary[j] = -directions[i][j]; } for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { pre_tensor[k + 3 * j] = temporary[k] * directions[i][j]; } } for (int j = 0; j < 6; j++) { H[i][j] = pre_tensor[etbt[j]]; } for (int j = 0; j < 3; j++) { H[i][3 + j] *= 2.0; } } H_org=H; vnl_matrix inputtopseudoinverse=H.transpose()*H; vnl_symmetric_eigensystem eig( inputtopseudoinverse); vnl_matrix pseudoInverse = eig.pinverse()*H.transpose(); itk::Index<3> ix; ImageType::Pointer corrected_diffusion = ImageType::New(); corrected_diffusion->SetRegions(size); corrected_diffusion->SetSpacing(m_GradientImagePointer->GetSpacing()); corrected_diffusion->SetOrigin(m_GradientImagePointer->GetOrigin()); corrected_diffusion->SetVectorLength(nof); corrected_diffusion->Allocate(); typedef itk::VariableLengthVector VariableVectorType; VariableVectorType variableLengthVector; variableLengthVector.SetSize(nof); // removing negative values for ( int x=0;xGetPixel(ix); for( int f=0;fSetPixel(ix, variableLengthVector); } } } vnl_vector org_data(nof); vnl_vector atten(nof-numberb0); double mean_b=0.0; double pixel=0.0; vnl_vector tensor (6); typedef itk::Image MaskImageType; MaskImageType::Pointer mask = MaskImageType::New(); mask->SetRegions(m_GradientImagePointer->GetLargestPossibleRegion().GetSize()); mask->SetSpacing(m_GradientImagePointer->GetSpacing()); mask->SetOrigin(m_GradientImagePointer->GetOrigin()); mask->Allocate(); int mask_cnt=0; for(int x=0;xGetPixel(ix); for (int i=0;im_B0Threshold) { mask->SetPixel(ix, 1); mask_cnt++; } else { mask->SetPixel(ix, 0); } } } } std::cout << "Number of voxels in mask: " << mask_cnt << std::endl; typedef itk::Image< itk::DiffusionTensor3D, 3 > TensorImageType; TensorImageType::Pointer tensorImg = TensorImageType::New(); tensorImg->SetRegions(m_GradientImagePointer->GetLargestPossibleRegion().GetSize()); tensorImg->SetSpacing(m_GradientImagePointer->GetSpacing()); tensorImg->SetOrigin(m_GradientImagePointer->GetOrigin()); tensorImg->Allocate(); vnl_matrix temp_tensor(3,3); vnl_vector eigen_vals(3); int number_of_bads=0; int old_number_of_bads=10000000000000000; int diff=1; vnl_vector< double> pixel_max(nof); vnl_vector< double> pixel_min(nof); for (int i=1;i0) { for (int x=0;xGetPixel(ix); itk::DiffusionTensor3D ten; if(mask->GetPixel(ix) == 1) { ix[0] = x; ix[1] = y; ix[2] = z; GradientVectorType pt = corrected_diffusion->GetPixel(ix); for (int i=0;i eigen_tensor(temp_tensor); eigen_vals[0]=eigen_tensor.get_eigenvalue(0); eigen_vals[1]=eigen_tensor.get_eigenvalue(1); eigen_vals[2]=eigen_tensor.get_eigenvalue(2); if( eigen_vals[0]>0.0 && eigen_vals[1]>0.0 && eigen_vals[2]>0.0) { tensorImg->SetPixel(ix, ten); }//end of if eigenvalues else { number_of_bads++; ten.Fill(0.0); tensorImg->SetPixel(ix, ten); for (int f=0;fpixel_max[f] || pt[f]< pixel_min[f]) { variableLengthVector[f] = CheckNeighbours(x,y,z,f,size); } } corrected_diffusion->SetPixel(ix, variableLengthVector); } } else { ten.Fill(0.0); tensorImg->SetPixel(ix, ten); } } } } diff=old_number_of_bads-number_of_bads; old_number_of_bads=number_of_bads; std::cout << "bad voxels: " << number_of_bads << std::endl; number_of_bads=0; } this->SetNthOutput(0, tensorImg); m_VectorImage = corrected_diffusion; m_MaskImage = mask; m_PseudoInverse = pseudoInverse; m_H = H_org; m_BVec=b_vec; m_Voxdim = vox_dim; } template void TensorReconstructionWithEigenvalueCorrectionFilter ::SetGradientImage( GradientDirectionContainerType *gradientDirection, const GradientImagesType *gradientImage ) { // Make sure crazy users did not call both AddGradientImage and // SetGradientImage if( m_GradientImageTypeEnumeration == GradientIsInManyImages ) { itkExceptionMacro( << "Cannot call both methods:" << "AddGradientImage and SetGradientImage. Please call only one of them."); } this->m_GradientDirectionContainer = gradientDirection; unsigned int numImages = gradientDirection->Size(); this->m_NumberOfBaselineImages = 0; this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages; // ensure that the gradient image we received has as many components as // the number of gradient directions if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + this->m_NumberOfGradientDirections ) { itkExceptionMacro( << this->m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages << "baselines = " << this->m_NumberOfGradientDirections + this->m_NumberOfBaselineImages << " directions specified but image has " << gradientImage->GetVectorLength() << " components."); } this->ProcessObject::SetNthInput( 0, const_cast< GradientImagesType* >(gradientImage) ); m_GradientImageTypeEnumeration = GradientIsInASingleImage; } template short TensorReconstructionWithEigenvalueCorrectionFilter ::CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size) { int init_i, init_j, init_c, limit_i, limit_j, limit_c; double tempsum=0.0; double temp_number=0.0; init_i=x-1; limit_i=x+2; if(x==0) init_i=x; else if(x==size[0]-1) limit_i=x+1; init_j=y-1; limit_j=y+2; if(y==0) init_j=y; else if(y==size[1]-1) init_j=y-1; init_c=z-1; limit_c=z+2; if(z==0) init_c=z; else if(z==size[2]-1) limit_c=z+1; for(int i=init_i; i ix; ix[0] = i; ix[1] = j; ix[2] = c; GradientVectorType p = m_GradientImagePointer->GetPixel(ix); if(p[f]>=0.0) { tempsum=tempsum+p[f]; temp_number++; } } } } if (temp_number==0.0) { tempsum=0.0; } else { tempsum=tempsum/temp_number; } short ret = (short)tempsum; return ret; } template void TensorReconstructionWithEigenvalueCorrectionFilter ::CalculateAttenuation(vnl_vector org_data,vnl_vector &atten,int nof, int numberb0) { double mean_b=0.0; for (int i=0;i void TensorReconstructionWithEigenvalueCorrectionFilter ::CalculateTensor(vnl_matrix pseudoInverse,vnl_vector atten,vnl_vector &tensor, int nof,int numberb0) { for (int i=0;i class ITK_EXPORT TensorToL2NormImageFilter : public ImageToImageFilter { public: typedef TensorToL2NormImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; itkTypeMacro (TensorToL2NormImageFilter, ImageToImageFilter); itkStaticConstMacro (ImageDimension, unsigned int, TOutputImage::ImageDimension); itkNewMacro (Self); typedef TInputImage InputImageType; typedef typename InputImageType::PixelType InputPixelType; typedef TOutputImage OutputImageType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename OutputImageType::RegionType OutputImageRegionType; protected: TensorToL2NormImageFilter(){}; ~TensorToL2NormImageFilter(){}; void PrintSelf (std::ostream& os, Indent indent) const { Superclass::PrintSelf (os, indent); } void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, int threadId); private: TensorToL2NormImageFilter (const Self&); void operator=(const Self&); }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkTensorToL2NormImageFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorToL2NormImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorToL2NormImageFilter.txx index afe17f1178..7dd9721927 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTensorToL2NormImageFilter.txx +++ b/Modules/DiffusionImaging/Algorithms/itkTensorToL2NormImageFilter.txx @@ -1,84 +1,99 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Tensor ToolKit - TTK Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorToL2NormImageFilter.txx $ Language: C++ Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ Version: $Revision: 68 $ Copyright (c) INRIA 2010. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _itk_TensorToL2NormImageFilter_txx_ #define _itk_TensorToL2NormImageFilter_txx_ #endif #include "itkTensorToL2NormImageFilter.h" #include #include namespace itk { template void TensorToL2NormImageFilter ::ThreadedGenerateData ( const OutputImageRegionType &outputRegionForThread, int threadId ) { typedef ImageRegionIterator IteratorOutputType; typedef ImageRegionConstIterator IteratorInputType; unsigned long numPixels = outputRegionForThread.GetNumberOfPixels(); unsigned long step = numPixels/100; unsigned long progress = 0; - + IteratorOutputType itOut(this->GetOutput(), outputRegionForThread); IteratorInputType itIn(this->GetInput(), outputRegionForThread); if( threadId==0 ) this->UpdateProgress (0.0); while(!itOut.IsAtEnd()) { if( this->GetAbortGenerateData() ) throw itk::ProcessAborted(__FILE__,__LINE__); OutputPixelType out = static_cast( 0.0 ); // be careful, overload in MedINRIA InputPixelType T = itIn.Get(); if ( !(T[0]==0 && T[1]==0 && T[2]==0 && T[3]==0 && T[4]==0 && T[5]==0) ) { double sum = T[0]*T[0] + T[3]*T[3] + T[5]*T[5] + T[1]*T[2]*2.0 + T[2]*T[4]*2.0 + T[1]*T[4]*2.0; out = static_cast( vcl_sqrt( sum )); } if( threadId==0 && step>0) { if( (progress%step)==0 ) this->UpdateProgress ( double(progress)/double(numPixels) ); } itOut.Set (out); ++progress; ++itOut; ++itIn; } if( threadId==0 ) this->UpdateProgress (1.0); } } // end of namespace diff --git a/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp index 0785d38b97..1f42facfbb 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp @@ -1,203 +1,218 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkTractDensityImageFilter.h" // VTK #include #include #include // misc #include namespace itk{ template< class OutputImageType > TractDensityImageFilter< OutputImageType >::TractDensityImageFilter() : m_BinaryOutput(false) , m_InvertImage(false) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_UseImageGeometry(false) { } template< class OutputImageType > TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter() { } template< class OutputImageType > itk::Point TractDensityImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractDensityImageFilter< OutputImageType >::GenerateData() { // generate upsampled image mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters mitk::Vector3D newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetRegions( upsampledRegion ); outImage->Allocate(); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); for (int i=0; iGetDeepCopy(); m_FiberBundle->ResampleFibers(minSpacing/10); vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); // fill output image for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Index<3> index; itk::ContinuousIndex contIndex; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; int px = index[0]; if (frac_x<0) { px -= 1; frac_x += 1; } int py = index[1]; if (frac_y<0) { py -= 1; frac_y += 1; } int pz = index[2]; if (frac_z<0) { pz -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (px < 0 || px >= w-1) continue; if (py < 0 || py >= h-1) continue; if (pz < 0 || pz >= d-1) continue; if (m_BinaryOutput) { outImageBufferPointer[( px + w*(py + h*pz ))] = 1; outImageBufferPointer[( px + w*(py+1+ h*pz ))] = 1; outImageBufferPointer[( px + w*(py + h*pz+h))] = 1; outImageBufferPointer[( px + w*(py+1+ h*pz+h))] = 1; outImageBufferPointer[( px+1 + w*(py + h*pz ))] = 1; outImageBufferPointer[( px+1 + w*(py + h*pz+h))] = 1; outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] = 1; outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] = 1; } else { outImageBufferPointer[( px + w*(py + h*pz ))] += ( frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz ))] += ( frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px + w*(py + h*pz+h))] += ( frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz+h))] += ( frac_x)*(1-frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz ))] += (1-frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz+h))] += (1-frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += (1-frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z); } } } if (!m_BinaryOutput) { OutPixelType max = 0; for (int i=0; i0) for (int i=0; i #include #include #include #include namespace itk{ template< class OutputImageType > class TractDensityImageFilter : public ImageSource< OutputImageType > { public: typedef TractDensityImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkNewMacro(Self); itkTypeMacro( TractDensityImageFilter, ImageSource ); /** Upsampling factor **/ itkSetMacro( UpsamplingFactor, unsigned int); itkGetMacro( UpsamplingFactor, unsigned int); /** Invert Image **/ itkSetMacro( InvertImage, bool); itkGetMacro( InvertImage, bool); /** Binary Output **/ itkSetMacro( BinaryOutput, bool); itkGetMacro( BinaryOutput, bool); /** Use input image geometry to initialize output image **/ itkSetMacro( UseImageGeometry, bool); itkGetMacro( UseImageGeometry, bool); itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer); itkSetMacro( InputImage, typename OutputImageType::Pointer); void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractDensityImageFilter(); virtual ~TractDensityImageFilter(); typename OutputImageType::Pointer m_InputImage; mitk::FiberBundleX::Pointer m_FiberBundle; unsigned int m_UpsamplingFactor; bool m_InvertImage; bool m_BinaryOutput; bool m_UseImageGeometry; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractDensityImageFilter.cpp" #endif #endif // __itkTractDensityImageFilter_h__ diff --git a/Modules/DiffusionImaging/Algorithms/itkTractsToFiberEndingsImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractsToFiberEndingsImageFilter.cpp index ca729da0ff..20cbbf4fd2 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractsToFiberEndingsImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractsToFiberEndingsImageFilter.cpp @@ -1,135 +1,150 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkTractsToFiberEndingsImageFilter.h" // VTK #include #include #include namespace itk{ template< class OutputImageType > TractsToFiberEndingsImageFilter< OutputImageType >::TractsToFiberEndingsImageFilter() : m_InvertImage(false) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_UseImageGeometry(false) { } template< class OutputImageType > TractsToFiberEndingsImageFilter< OutputImageType >::~TractsToFiberEndingsImageFilter() { } template< class OutputImageType > itk::Point TractsToFiberEndingsImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractsToFiberEndingsImageFilter< OutputImageType >::GenerateData() { // generate upsampled image mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters mitk::Vector3D newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetRegions( upsampledRegion ); outImage->Allocate(); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); for (int i=0; i fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); // fill output image if (numPoints>0) { itk::Point vertex = GetItkPoint(fiberPolyData->GetPoint(points[0])); itk::Index<3> index; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->SetPixel(index, 1); } if (numPoints>2) { itk::Point vertex = GetItkPoint(fiberPolyData->GetPoint(points[numPoints-1])); itk::Index<3> index; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->SetPixel(index, 1); } } if (m_InvertImage) for (int i=0; i #include #include #include #include namespace itk{ template< class OutputImageType > class TractsToFiberEndingsImageFilter : public ImageSource< OutputImageType > { public: typedef TractsToFiberEndingsImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkNewMacro(Self); itkTypeMacro( TractsToFiberEndingsImageFilter, ImageSource ); /** Upsampling factor **/ itkSetMacro( UpsamplingFactor, unsigned int); itkGetMacro( UpsamplingFactor, unsigned int); /** Invert Image **/ itkSetMacro( InvertImage, bool); itkGetMacro( InvertImage, bool); itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer); itkSetMacro( InputImage, typename OutputImageType::Pointer); /** Use input image geometry to initialize output image **/ itkSetMacro( UseImageGeometry, bool); itkGetMacro( UseImageGeometry, bool); void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractsToFiberEndingsImageFilter(); virtual ~TractsToFiberEndingsImageFilter(); mitk::FiberBundleX::Pointer m_FiberBundle; unsigned int m_UpsamplingFactor; bool m_InvertImage; bool m_UseImageGeometry; typename OutputImageType::Pointer m_InputImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToFiberEndingsImageFilter.cpp" #endif #endif // __itkTractsToFiberEndingsImageFilter_h__ diff --git a/Modules/DiffusionImaging/Algorithms/itkTractsToRgbaImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractsToRgbaImageFilter.cpp index 933370c9ce..128f5bb525 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractsToRgbaImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractsToRgbaImageFilter.cpp @@ -1,270 +1,285 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkTractsToRgbaImageFilter.h" // VTK #include #include #include // misc #include namespace itk{ template< class OutputImageType > TractsToRgbaImageFilter< OutputImageType >::TractsToRgbaImageFilter() : m_BinaryOutput(false) , m_InvertImage(false) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_UseImageGeometry(false) { } template< class OutputImageType > TractsToRgbaImageFilter< OutputImageType >::~TractsToRgbaImageFilter() { } template< class OutputImageType > itk::Point TractsToRgbaImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractsToRgbaImageFilter< OutputImageType >::GenerateData() { if(&typeid(OutPixelType) != &typeid(itk::RGBAPixel)) return; // generate upsampled image mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters mitk::Vector3D newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetRegions( upsampledRegion ); outImage->Allocate(); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output unsigned char* outImageBufferPointer = (unsigned char*)outImage->GetBufferPointer(); float* buffer = new float[w*h*d*4]; for (int i=0; iGetDeepCopy(); m_FiberBundle->ResampleFibers(minSpacing/10); vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); // calc directions (which are used as weights) std::list< itk::Point > rgbweights; std::list intensities; for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Point vertexPost = GetItkPoint(fiberPolyData->GetPoint(points[j+1])); itk::Point dir; dir[0] = fabs((vertexPost[0] - vertex[0]) * outImage->GetSpacing()[0]); dir[1] = fabs((vertexPost[1] - vertex[1]) * outImage->GetSpacing()[1]); dir[2] = fabs((vertexPost[2] - vertex[2]) * outImage->GetSpacing()[2]); rgbweights.push_back(dir); float intensity = sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]); intensities.push_back(intensity); // last point gets same as previous one if(j==numPoints-2) { rgbweights.push_back(dir); intensities.push_back(intensity); } } // fill output image for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Index<3> index; itk::ContinuousIndex contIndex; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; int px = index[0]; if (frac_x<0) { px -= 1; frac_x += 1; } int py = index[1]; if (frac_y<0) { py -= 1; frac_y += 1; } int pz = index[2]; if (frac_z<0) { pz -= 1; frac_z += 1; } // int coordinates inside image? if (px < 0 || px >= w-1) continue; if (py < 0 || py >= h-1) continue; if (pz < 0 || pz >= d-1) continue; float scale = 100 * pow((float)m_UpsamplingFactor,3); itk::Point rgbweight = rgbweights.front(); rgbweights.pop_front(); float intweight = intensities.front(); intensities.pop_front(); // add to r-channel in output image buffer[0+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale; // add to g-channel in output image buffer[1+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale; // add to b-channel in output image buffer[2+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale; // add to a-channel in output image buffer[3+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * intweight * scale; } } float maxRgb = 0.000000001; float maxInt = 0.000000001; int numPix; numPix = w*h*d*4; // calc maxima for(int i=0; i maxRgb) maxRgb = buffer[i]; } else { if(buffer[i] > maxInt) maxInt = buffer[i]; } } // write output, normalized uchar 0..255 for(int i=0; i #include #include #include #include namespace itk{ template< class OutputImageType > class TractsToRgbaImageFilter : public ImageSource< OutputImageType > { public: typedef TractsToRgbaImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; typedef itk::Image InputImageType; itkNewMacro(Self); itkTypeMacro( TractsToRgbaImageFilter, ImageSource ); /** Upsampling factor **/ itkSetMacro( UpsamplingFactor, unsigned int); itkGetMacro( UpsamplingFactor, unsigned int); /** Invert Image **/ itkSetMacro( InvertImage, bool); itkGetMacro( InvertImage, bool); /** Binary Output **/ itkSetMacro( BinaryOutput, bool); itkGetMacro( BinaryOutput, bool); itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer); itkSetMacro( InputImage, typename InputImageType::Pointer); /** Use input image geometry to initialize output image **/ itkSetMacro( UseImageGeometry, bool); itkGetMacro( UseImageGeometry, bool); void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractsToRgbaImageFilter(); virtual ~TractsToRgbaImageFilter(); mitk::FiberBundleX::Pointer m_FiberBundle; unsigned int m_UpsamplingFactor; bool m_InvertImage; bool m_BinaryOutput; bool m_UseImageGeometry; typename InputImageType::Pointer m_InputImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToRgbaImageFilter.cpp" #endif #endif // __itkTractsToRgbaImageFilter_h__ diff --git a/Modules/DiffusionImaging/Algorithms/mitkTractAnalyzer.cpp b/Modules/DiffusionImaging/Algorithms/mitkTractAnalyzer.cpp index d5e9be0f60..9009f406c0 100644 --- a/Modules/DiffusionImaging/Algorithms/mitkTractAnalyzer.cpp +++ b/Modules/DiffusionImaging/Algorithms/mitkTractAnalyzer.cpp @@ -1,162 +1,177 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __mitkTractAnalyzer_cpp #define __mitkTractAnalyzer_cpp #include #include #include #include #include #include #include using namespace std; namespace mitk { TractAnalyzer::TractAnalyzer() { } void TractAnalyzer::BuildGraph(itk::Index<3> startPoint, itk::Index<3> endPoint) { typedef itk::ShortestPathImageFilter ShortestPathFilterType; typedef itk::ShortestPathCostFunctionTbss CostFunctionType; FloatImageType::Pointer meanSkeleton; mitk::CastToItkImage(m_InputImage, meanSkeleton); // Only use the mitk image if(meanSkeleton) { CostFunctionType::Pointer costFunction = CostFunctionType::New(); costFunction->SetImage(meanSkeleton); costFunction->SetStartIndex(startPoint); costFunction->SetEndIndex(endPoint); costFunction->SetThreshold(m_Threshold); ShortestPathFilterType::Pointer pathFinder = ShortestPathFilterType::New(); pathFinder->SetCostFunction(costFunction); pathFinder->SetFullNeighborsMode(true); //pathFinder->SetCalcMode(ShortestPathFilterType::A_STAR); pathFinder->SetInput(meanSkeleton); pathFinder->SetStartIndex(startPoint); pathFinder->SetEndIndex(endPoint); pathFinder->Update(); m_Path = pathFinder->GetVectorPath(); m_RoiImg = pathFinder->GetOutput(); } } void TractAnalyzer::MeasureRoi() { // Output two types ProjectionsImageType::SizeType size = m_Projections->GetLargestPossibleRegion().GetSize(); std::ofstream file(m_FileName.c_str()); std::vector individuals; for(int i=0; i group = m_Groups[i]; for(int j=0; j ix = m_Roi[k]; itk::Index<4> ix4; ix4[0] = ix[0]; ix4[1] = ix[1]; ix4[2] = ix[2]; ix4[3] = j; float f = m_Projections->GetPixel(ix4); file << f << " "; } file << "\n"; } file.close(); // Write the long format output std::ofstream fileLong(m_FileNameLong.c_str()); fileLong << "ID " << "group " << "position " << "value\n"; for(int i=0; i ix = m_Roi[i]; itk::Index<4> ix4; ix4[0] = ix[0]; ix4[1] = ix[1]; ix4[2] = ix[2]; ix4[3] = j; float f = m_Projections->GetPixel(ix4); fileLong << "ID" << j << " " << individuals[j] << " " << "pos" << i << " "<< f << "\n"; } } fileLong.close(); } } #endif diff --git a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h index 4789f31764..a7883718d9 100644 --- a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h +++ b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h @@ -1,145 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkDiffusionImage__h #define __mitkDiffusionImage__h #include "mitkImage.h" #include "itkVectorImage.h" #include "itkVectorImageToImageAdaptor.h" +#include +#include namespace mitk { - /** +/** * \brief this class encapsulates diffusion volumes (vectorimages not * yet supported by mitkImage) */ - template - class DiffusionImage : public Image - { - - public: - typedef TPixelType PixelType; - typedef typename itk::VectorImage - ImageType; - typedef vnl_vector_fixed< double, 3 > GradientDirectionType; - typedef itk::VectorContainer< unsigned int, - GradientDirectionType > GradientDirectionContainerType; - typedef itk::VectorImageToImageAdaptor< TPixelType, 3 > - AdaptorType; - typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType; - - mitkClassMacro( DiffusionImage, Image ); - itkNewMacro(Self); - - //void SetRequestedRegionToLargestPossibleRegion(); - //bool RequestedRegionIsOutsideOfTheBufferedRegion(); - //virtual bool VerifyRequestedRegion(); - //void SetRequestedRegion(itk::DataObject *data); - - void AverageRedundantGradients(double precision); - - GradientDirectionContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions); - - void CorrectDKFZBrokenGradientScheme(double precision); - - typename ImageType::Pointer GetVectorImage() - { return m_VectorImage; } - void SetVectorImage(typename ImageType::Pointer image ) - { this->m_VectorImage = image; } - - void InitializeFromVectorImage(); - void SetDisplayIndexForRendering(int displayIndex); - - GradientDirectionContainerType::Pointer GetDirections() - { return m_Directions; } - void SetDirections( GradientDirectionContainerType::Pointer directions ) - { this->m_Directions = directions; } - void SetDirections(const std::vector > directions) - { - m_Directions = GradientDirectionContainerType::New(); - for(unsigned int i=0; iInsertElement( i, directions[i].Get_vnl_vector() ); - } - } - GradientDirectionContainerType::Pointer GetOriginalDirections() - { return m_OriginalDirections; } - void SetOriginalDirections( GradientDirectionContainerType::Pointer directions ) - { this->m_OriginalDirections = directions; this->ApplyMeasurementFrame(); } - void SetOriginalDirections(const std::vector > directions) - { - m_OriginalDirections = GradientDirectionContainerType::New(); - for(unsigned int i=0; iInsertElement( i, directions[i].Get_vnl_vector() ); - } - this->ApplyMeasurementFrame(); - } - - MeasurementFrameType GetMeasurementFrame() - { return m_MeasurementFrame; } - void SetMeasurementFrame( MeasurementFrameType mFrame ) - { this->m_MeasurementFrame = mFrame; this->ApplyMeasurementFrame(); } - - itkGetMacro(B_Value, float); - itkSetMacro(B_Value, float); - - float GetB_Value(int i) - { - if(i > m_Directions->Size()-1) - return -1; - - if(m_Directions->ElementAt(i).one_norm() <= 0.0) - { - return 0; - } - else - { - double twonorm = m_Directions->ElementAt(i).two_norm(); - return m_B_Value*twonorm*twonorm ; - } - } - - bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); - - int GetNumDirections(); - int GetNumB0(); - std::vector GetB0Indices(); - bool IsMultiBval(); - - protected: - DiffusionImage(); - virtual ~DiffusionImage(); - - void ApplyMeasurementFrame(); - - typename ImageType::Pointer m_VectorImage; - GradientDirectionContainerType::Pointer m_Directions; - GradientDirectionContainerType::Pointer m_OriginalDirections; - float m_B_Value; - typename AdaptorType::Pointer m_VectorImageAdaptor; - int m_DisplayIndex; - MeasurementFrameType m_MeasurementFrame; - }; +template +class DiffusionImage : public Image +{ + +public: + typedef TPixelType PixelType; + typedef typename itk::VectorImage + ImageType; + typedef vnl_vector_fixed< double, 3 > GradientDirectionType; + typedef itk::VectorContainer< unsigned int, + GradientDirectionType > GradientDirectionContainerType; + typedef itk::VectorImageToImageAdaptor< TPixelType, 3 > + AdaptorType; + typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType; + + // BValue Map + // key := b-Value + // value := indicesVector (containing corresponding gradient directions for a b-Value-Shell + typedef std::vector< unsigned int > IndicesVector; + typedef std::map< double , IndicesVector > BValueMap; + + mitkClassMacro( DiffusionImage, Image ); + itkNewMacro(Self); + + + void AverageRedundantGradients(double precision); + + GradientDirectionContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions); + + void CorrectDKFZBrokenGradientScheme(double precision); + + typename ImageType::Pointer GetVectorImage() { return m_VectorImage; } + void SetVectorImage(typename ImageType::Pointer image ) { this->m_VectorImage = image; } + + void InitializeFromVectorImage(); + void SetDisplayIndexForRendering(int displayIndex); + + GradientDirectionContainerType::Pointer GetDirections() { return m_Directions; } + void SetDirections( GradientDirectionContainerType::Pointer directions ) { this->m_Directions = directions; } + void SetDirections(const std::vector > directions); + + GradientDirectionContainerType::Pointer GetOriginalDirections() { return m_OriginalDirections; } + void SetOriginalDirections( GradientDirectionContainerType::Pointer directions ) { this->m_OriginalDirections = directions; this->ApplyMeasurementFrame(); } + void SetOriginalDirections(const std::vector > directions); + + MeasurementFrameType GetMeasurementFrame() { return m_MeasurementFrame; } + void SetMeasurementFrame( MeasurementFrameType mFrame ) { this->m_MeasurementFrame = mFrame; this->ApplyMeasurementFrame(); } + + bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); + int GetNumDirections(); + int GetNumB0(); + + float GetB_Value(int i); + bool IsMultiBval(); + void UpdateBValueList(); + + IndicesVector GetB0Indices(); + + itkGetMacro(B_Value, float); + itkSetMacro(B_Value, float); + + BValueMap GetB_ValueMap(){ return m_B_ValueMap; } + + void AddDirectionsContainerObserver(); + void RemoveDirectionsContainerObserver(); + +protected: + DiffusionImage(); + virtual ~DiffusionImage(); + + void ApplyMeasurementFrame(); + + typename ImageType::Pointer m_VectorImage; + GradientDirectionContainerType::Pointer m_Directions; + GradientDirectionContainerType::Pointer m_OriginalDirections; + float m_B_Value; + typename AdaptorType::Pointer m_VectorImageAdaptor; + int m_DisplayIndex; + MeasurementFrameType m_MeasurementFrame; + BValueMap m_B_ValueMap; + + + + unsigned long m_DirectionsObserverTag; +}; } // namespace mitk #include "mitkDiffusionImage.txx" #endif /* __mitkDiffusionImage__h */ diff --git a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx index 53eec36178..285fdb52ba 100644 --- a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx +++ b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx @@ -1,417 +1,512 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "mitkImageCast.h" template mitk::DiffusionImage::DiffusionImage() -: m_VectorImage(0), m_Directions(0), m_OriginalDirections(0), m_B_Value(-1.0), m_VectorImageAdaptor(0) + : m_VectorImage(0), m_Directions(0), m_OriginalDirections(0), m_B_Value(-1.0), m_VectorImageAdaptor(0) { MeasurementFrameType mf; for(int i=0; i<3; i++) for(int j=0; j<3; j++) mf[i][j] = 0; for(int i=0; i<3; i++) mf[i][i] = 1; m_MeasurementFrame = mf; } template mitk::DiffusionImage::~DiffusionImage() { - + // Remove Observer for m_Directions + RemoveDirectionsContainerObserver(); } template void mitk::DiffusionImage ::InitializeFromVectorImage() { if(!m_VectorImage || !m_Directions || m_B_Value==-1.0) { MITK_INFO << "DiffusionImage could not be initialized. Set all members first!" << std::endl; return; } // find bzero index int firstZeroIndex = -1; for(GradientDirectionContainerType::ConstIterator it = m_Directions->Begin(); - it != m_Directions->End(); ++it) + it != m_Directions->End(); ++it) { firstZeroIndex++; GradientDirectionType g = it.Value(); if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) break; } typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); img->SetSpacing( m_VectorImage->GetSpacing() ); // Set the image spacing img->SetOrigin( m_VectorImage->GetOrigin() ); // Set the image origin img->SetDirection( m_VectorImage->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( m_VectorImage->GetLargestPossibleRegion()); img->SetBufferedRegion( m_VectorImage->GetLargestPossibleRegion() ); img->Allocate(); int vecLength = m_VectorImage->GetVectorLength(); InitializeByItk( img.GetPointer(), 1, vecLength ); //for(int i=0; i itw (img, img->GetLargestPossibleRegion() ); - itw = itw.Begin(); + itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); + itw = itw.Begin(); - itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); - itr = itr.Begin(); + itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); + itr = itr.Begin(); - while(!itr.IsAtEnd()) - { - itw.Set(itr.Get().GetElement(firstZeroIndex)); - ++itr; - ++itw; - } + while(!itr.IsAtEnd()) + { + itw.Set(itr.Get().GetElement(firstZeroIndex)); + ++itr; + ++itw; + } - // init - SetImportVolume(img->GetBufferPointer());//, 0, 0, CopyMemory); - //SetVolume( img->GetBufferPointer(), i ); + // init + SetImportVolume(img->GetBufferPointer());//, 0, 0, CopyMemory); + //SetVolume( img->GetBufferPointer(), i ); //} m_DisplayIndex = firstZeroIndex; MITK_INFO << "Diffusion-Image successfully initialized."; } template void mitk::DiffusionImage ::SetDisplayIndexForRendering(int displayIndex) { int index = displayIndex; int vecLength = m_VectorImage->GetVectorLength(); index = index > vecLength-1 ? vecLength-1 : index; if( m_DisplayIndex != index ) { typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); CastToItkImage(this, img); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(index)); ++itr; ++itw; } } m_DisplayIndex = index; } //template //bool mitk::DiffusionImage::RequestedRegionIsOutsideOfTheBufferedRegion() //{ // return false; //} // //template //void mitk::DiffusionImage::SetRequestedRegion(itk::DataObject * /*data*/) //{ //} // //template //void mitk::DiffusionImage::SetRequestedRegionToLargestPossibleRegion() //{ //} // //template //bool mitk::DiffusionImage::VerifyRequestedRegion() //{ // return true; //} //template //void mitk::DiffusionImage::DuplicateIfSingleSlice() //{ // // new image // typename ImageType::Pointer oldImage = m_Image; // m_Image = ImageType::New(); // m_Image->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing // m_Image->SetOrigin( oldImage->GetOrigin() ); // Set the image origin // m_Image->SetDirection( oldImage->GetDirection() ); // Set the image direction // typename ImageType::RegionType region = oldImage->GetLargestPossibleRegion(); // if(region.GetSize(0) == 1) // region.SetSize(0,3); // if(region.GetSize(1) == 1) // region.SetSize(1,3); // if(region.GetSize(2) == 1) // region.SetSize(2,3); // m_Image->SetLargestPossibleRegion( region ); // m_Image->SetVectorLength( m_Directions->size() ); // m_Image->SetBufferedRegion( region ); // m_Image->Allocate(); // // // average image data that corresponds to identical directions // itk::ImageRegionIterator< ImageType > newIt(m_Image, region); // newIt.GoToBegin(); // itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); // oldIt.GoToBegin(); // // while(!newIt.IsAtEnd()) // { // newIt.Set(oldIt.Get()); // ++newIt; // ++oldIt; // if(oldIt.IsAtEnd()) // oldIt.GoToBegin(); // } // //} template bool mitk::DiffusionImage::AreAlike(GradientDirectionType g1, - GradientDirectionType g2, - double precision) + GradientDirectionType g2, + double precision) { GradientDirectionType diff = g1 - g2; return diff.two_norm() < precision; } template void mitk::DiffusionImage::CorrectDKFZBrokenGradientScheme(double precision) { GradientDirectionContainerType::Pointer directionSet = CalcAveragedDirectionSet(precision, m_Directions); if(directionSet->size() < 7) { MITK_INFO << "Too few directions, assuming and correcting DKFZ-bogus sequence details."; double v [7][3] = - {{ 0, 0, 0 }, - {-0.707057, 0, 0.707057 }, - { 0.707057, 0, 0.707057 }, - { 0, 0.707057, 0.707057 }, - { 0, 0.707057, -0.707057 }, - {-0.707057, 0.707057, 0 }, - { 0.707057, 0.707057, 0 } }; + {{ 0, 0, 0 }, + {-0.707057, 0, 0.707057 }, + { 0.707057, 0, 0.707057 }, + { 0, 0.707057, 0.707057 }, + { 0, 0.707057, -0.707057 }, + {-0.707057, 0.707057, 0 }, + { 0.707057, 0.707057, 0 } }; int i=0; for(GradientDirectionContainerType::Iterator it = m_OriginalDirections->Begin(); - it != m_OriginalDirections->End(); ++it) + it != m_OriginalDirections->End(); ++it) { it.Value().set(v[i++%7]); } ApplyMeasurementFrame(); } } template mitk::DiffusionImage::GradientDirectionContainerType::Pointer mitk::DiffusionImage::CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionContainerType::Pointer newDirections = GradientDirectionContainerType::New(); // fill new direction container for(GradientDirectionContainerType::ConstIterator gdcitOld = directions->Begin(); - gdcitOld != directions->End(); ++gdcitOld) + gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionContainerType::ConstIterator gdcitNew = newDirections->Begin(); - gdcitNew != newDirections->End(); ++gdcitNew) + gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } template void mitk::DiffusionImage::AverageRedundantGradients(double precision) { GradientDirectionContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, m_Directions); GradientDirectionContainerType::Pointer newOriginalDirs = - CalcAveragedDirectionSet(precision, m_OriginalDirections); + CalcAveragedDirectionSet(precision, m_OriginalDirections); // if sizes equal, we do not need to do anything in this function if(m_Directions->size() == newDirs->size() || m_OriginalDirections->size() == newOriginalDirs->size()) return; GradientDirectionContainerType::Pointer oldDirections = m_Directions; GradientDirectionContainerType::Pointer oldOriginalDirections = m_OriginalDirections; m_Directions = newDirs; m_OriginalDirections = newOriginalDirs; // new image typename ImageType::Pointer oldImage = m_VectorImage; m_VectorImage = ImageType::New(); m_VectorImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing m_VectorImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin m_VectorImage->SetDirection( oldImage->GetDirection() ); // Set the image direction m_VectorImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->SetVectorLength( m_Directions->size() ); m_VectorImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(m_VectorImage, m_VectorImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel typename ImageType::PixelType newVec; newVec.SetSize(m_Directions->size()); newVec.AllocateElements(m_Directions->size()); std::vector > dirIndices; for(GradientDirectionContainerType::ConstIterator gdcitNew = m_Directions->Begin(); - gdcitNew != m_Directions->End(); ++gdcitNew) + gdcitNew != m_Directions->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionContainerType::ConstIterator gdcitOld = oldDirections->Begin(); - gdcitOld != oldDirections->End(); ++gdcitOld) + gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress //typename ImageType::IndexType ind = newIt.GetIndex(); //ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates typename ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; i void mitk::DiffusionImage::ApplyMeasurementFrame() { + RemoveDirectionsContainerObserver(); + m_Directions = GradientDirectionContainerType::New(); int c = 0; for(GradientDirectionContainerType::ConstIterator gdcit = m_OriginalDirections->Begin(); - gdcit != m_OriginalDirections->End(); ++gdcit) + gdcit != m_OriginalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); vec = vec.pre_multiply(m_MeasurementFrame); m_Directions->InsertElement(c, vec); c++; } + + UpdateBValueList(); + + AddDirectionsContainerObserver(); + + } // returns number of gradients template int mitk::DiffusionImage::GetNumDirections() { int gradients = m_OriginalDirections->Size(); for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { gradients--; } return gradients; } // returns number of not diffusion weighted images template int mitk::DiffusionImage::GetNumB0() { int b0 = 0; for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { b0++; } return b0; } // returns a list of indices belonging to the not diffusion weighted images template -std::vector mitk::DiffusionImage::GetB0Indices() +typename mitk::DiffusionImage::IndicesVector mitk::DiffusionImage::GetB0Indices() { - std::vector indices; + IndicesVector indices; for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { indices.push_back(i); } return indices; } template bool mitk::DiffusionImage::IsMultiBval() { int gradients = m_OriginalDirections->Size(); for (int i=0; i0 && std::fabs(m_B_Value-GetB_Value(i))>50) return true; return false; } + +template +void mitk::DiffusionImage::UpdateBValueList() +{ + m_B_ValueMap.clear(); + + GradientDirectionContainerType::ConstIterator gdcit; + for( gdcit = this->m_Directions->Begin(); gdcit != this->m_Directions->End(); ++gdcit) + { + float currentBvalue = std::floor(GetB_Value(gdcit.Index())); + double rounded = int((currentBvalue+7.5)/10)*10; + m_B_ValueMap[rounded].push_back(gdcit.Index()); + } + + /* + BValueMap::iterator it = m_B_ValueMap.begin(); + for(;it != m_B_ValueMap.end(); it++) + { + MITK_INFO << it->first << " : " << it->second.size(); + } + */ + +} + +template +float mitk::DiffusionImage::GetB_Value(int i) +{ + if(i > m_Directions->Size()-1) + return -1; + + if(m_Directions->ElementAt(i).one_norm() <= 0.0) + { + return 0; + } + else + { + double twonorm = m_Directions->ElementAt(i).two_norm(); + return m_B_Value*twonorm*twonorm ; + } +} + +template +void mitk::DiffusionImage::SetOriginalDirections(const std::vector > directions) +{ + m_OriginalDirections = GradientDirectionContainerType::New(); + for(unsigned int i=0; iInsertElement( i, directions[i].Get_vnl_vector() ); + } + this->ApplyMeasurementFrame(); +} + +template +void mitk::DiffusionImage::SetDirections(const std::vector > directions) +{ + + RemoveDirectionsContainerObserver(); + + m_Directions = GradientDirectionContainerType::New(); + for(unsigned int i=0; iInsertElement( i, directions[i].Get_vnl_vector() ); + } + + UpdateBValueList(); + AddDirectionsContainerObserver(); +} + +template +void mitk::DiffusionImage::AddDirectionsContainerObserver() +{ + // Add Modified Observer to invoke an UpdateBValueList by modifieng the DirectionsContainer (m_Directions) + typedef DiffusionImage< TPixelType > Self; + typedef itk::SimpleMemberCommand< Self > DCCommand ; + typename DCCommand::Pointer command = DCCommand::New(); + command->SetCallbackFunction(this, &Self::UpdateBValueList); +} + +template +void mitk::DiffusionImage::RemoveDirectionsContainerObserver() +{ + if(m_Directions){ + m_Directions->RemoveAllObservers(); + } +} + diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index f9efed5e92..f254971e40 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,1260 +1,1288 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleX.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; //const char* mitk::FiberBundleX::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity"; const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "FA_Values"; const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) - : m_CurrentColorCoding(NULL) - , m_NumFibers(0) + : m_CurrentColorCoding(NULL) + , m_NumFibers(0) { - m_FiberPolyData = vtkSmartPointer::New(); - if (fiberPolyData != NULL) - { - vtkSmartPointer cleaner = vtkSmartPointer::New(); - cleaner->SetInput(fiberPolyData); - cleaner->Update(); - fiberPolyData = cleaner->GetOutput(); - - m_FiberPolyData->DeepCopy(fiberPolyData); - this->DoColorCodingOrientationBased(); - } - - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) - MITK_DEBUG << "ok"; - - vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); - if (tmpColors!=NULL) - { - int tmpColorss = tmpColors->GetNumberOfTuples(); - int tmpColorc = tmpColors->GetNumberOfComponents(); - } + m_FiberPolyData = vtkSmartPointer::New(); + if (fiberPolyData != NULL) + { + vtkSmartPointer cleaner = vtkSmartPointer::New(); + cleaner->SetInput(fiberPolyData); + cleaner->Update(); + fiberPolyData = cleaner->GetOutput(); + + m_FiberPolyData->DeepCopy(fiberPolyData); + this->DoColorCodingOrientationBased(); + } - m_NumFibers = m_FiberPolyData->GetNumberOfLines(); + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) + MITK_DEBUG << "ok"; - this->UpdateFiberGeometry(); - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - this->GenerateFiberIds(); + vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); + if (tmpColors!=NULL) + { + int tmpColorss = tmpColors->GetNumberOfTuples(); + int tmpColorc = tmpColors->GetNumberOfComponents(); + } + + m_NumFibers = m_FiberPolyData->GetNumberOfLines(); + + this->UpdateFiberGeometry(); + this->SetColorCoding(COLORCODING_ORIENTATION_BASED); + this->GenerateFiberIds(); } mitk::FiberBundleX::~FiberBundleX() { } mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() { - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); + mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) - MITK_DEBUG << "ok"; + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) + MITK_DEBUG << "ok"; - vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); - int tmpColorss = tmpColors->GetNumberOfTuples(); - int tmpColorc = tmpColors->GetNumberOfComponents(); + vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); + int tmpColorss = tmpColors->GetNumberOfTuples(); + int tmpColorc = tmpColors->GetNumberOfComponents(); - newFib->SetColorCoding(m_CurrentColorCoding); - return newFib; + newFib->SetColorCoding(m_CurrentColorCoding); + return newFib; } vtkSmartPointer mitk::FiberBundleX::GeneratePolyDataByIds(std::vector fiberIds) { - MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n"; - MITK_DEBUG << "Number of new Fibers: " << fiberIds.size(); - // iterate through the vectorcontainer hosting all desired fiber Ids - - vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); - vtkSmartPointer newLineSet = vtkSmartPointer::New(); - vtkSmartPointer newPointSet = vtkSmartPointer::New(); - - // if FA array available, initialize fa double array - // if color orient array is available init color array - vtkSmartPointer faValueArray; - vtkSmartPointer colorsT; - //colors and alpha value for each single point, RGBA = 4 components - unsigned char rgba[4] = {0,0,0,0}; - int componentSize = sizeof(rgba); - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ - MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle"; - faValueArray = vtkSmartPointer::New(); - } - - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ - MITK_DEBUG << "colorValues available, init array for new fiberbundle"; - colorsT = vtkUnsignedCharArray::New(); - colorsT->SetNumberOfComponents(componentSize); - colorsT->SetName(COLORCODING_ORIENTATION_BASED); - } + MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n"; + MITK_DEBUG << "Number of new Fibers: " << fiberIds.size(); + // iterate through the vectorcontainer hosting all desired fiber Ids + + vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); + vtkSmartPointer newLineSet = vtkSmartPointer::New(); + vtkSmartPointer newPointSet = vtkSmartPointer::New(); + + // if FA array available, initialize fa double array + // if color orient array is available init color array + vtkSmartPointer faValueArray; + vtkSmartPointer colorsT; + //colors and alpha value for each single point, RGBA = 4 components + unsigned char rgba[4] = {0,0,0,0}; + int componentSize = sizeof(rgba); + + if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ + MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle"; + faValueArray = vtkSmartPointer::New(); + } + if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ + MITK_DEBUG << "colorValues available, init array for new fiberbundle"; + colorsT = vtkUnsignedCharArray::New(); + colorsT->SetNumberOfComponents(componentSize); + colorsT->SetName(COLORCODING_ORIENTATION_BASED); + } - std::vector::iterator finIt = fiberIds.begin(); - while ( finIt != fiberIds.end() ) - { - if (*finIt < 0 || *finIt>GetNumFibers()){ - MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; - break; - } - vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); + std::vector::iterator finIt = fiberIds.begin(); + while ( finIt != fiberIds.end() ) + { + if (*finIt < 0 || *finIt>GetNumFibers()){ + MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; + break; + } + + vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); - vtkSmartPointer fibPoints = fiber->GetPoints(); + vtkSmartPointer fibPoints = fiber->GetPoints(); - vtkSmartPointer newFiber = vtkSmartPointer::New(); - newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); + vtkSmartPointer newFiber = vtkSmartPointer::New(); + newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); - for(int i=0; iGetNumberOfPoints(); i++) - { - // MITK_DEBUG << "id: " << fiber->GetPointId(i); - // MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; - newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); - newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); + for(int i=0; iGetNumberOfPoints(); i++) + { + // MITK_DEBUG << "id: " << fiber->GetPointId(i); + // MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; + newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); + newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ - // MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); - } + if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ + // MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); + } - if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ - // MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; - } - } + if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ + // MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; + } + } - newLineSet->InsertNextCell(newFiber); - ++finIt; - } + newLineSet->InsertNextCell(newFiber); + ++finIt; + } - newFiberPolyData->SetPoints(newPointSet); - newFiberPolyData->SetLines(newLineSet); - MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); - MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); - MITK_DEBUG << "=====================\n"; + newFiberPolyData->SetPoints(newPointSet); + newFiberPolyData->SetLines(newLineSet); + MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); + MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); + MITK_DEBUG << "=====================\n"; - // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); - return newFiberPolyData; + // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); + return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib) { + if (fib==NULL) + { + MITK_WARN << "trying to call AddBundle with NULL argument"; + return NULL; + } - vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); - vtkSmartPointer vNewLines = vtkSmartPointer::New(); - vtkSmartPointer vNewPoints = vtkSmartPointer::New(); - - vtkSmartPointer vLines = m_FiberPolyData->GetLines(); - vLines->InitTraversal(); + vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); + vtkSmartPointer vNewLines = vtkSmartPointer::New(); + vtkSmartPointer vNewPoints = vtkSmartPointer::New(); - // add current fiber bundle - int numFibers = GetNumFibers(); - for( int i=0; iGetNextCell ( numPoints, points ); + vtkSmartPointer vLines = m_FiberPolyData->GetLines(); + vLines->InitTraversal(); - vtkSmartPointer container = vtkSmartPointer::New(); - for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); - container->GetPointIds()->InsertNextId(id); + vtkIdType numPoints(0); + vtkIdType* points(NULL); + vLines->GetNextCell ( numPoints, points ); + + vtkSmartPointer container = vtkSmartPointer::New(); + for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); + container->GetPointIds()->InsertNextId(id); + } + vNewLines->InsertNextCell(container); } - vNewLines->InsertNextCell(container); - } - - vLines = fib->m_FiberPolyData->GetLines(); - vLines->InitTraversal(); - - // add new fiber bundle - numFibers = fib->GetNumFibers(); - for( int i=0; iGetNextCell ( numPoints, points ); - - vtkSmartPointer container = vtkSmartPointer::New(); - for( int j=0; jm_FiberPolyData->GetLines(); + vLines->InitTraversal(); + + // add new fiber bundle + numFibers = fib->GetNumFibers(); + for( int i=0; iInsertNextPoint(fib->m_FiberPolyData->GetPoint(points[j])); - container->GetPointIds()->InsertNextId(id); + vtkIdType numPoints(0); + vtkIdType* points(NULL); + vLines->GetNextCell ( numPoints, points ); + + vtkSmartPointer container = vtkSmartPointer::New(); + for( int j=0; jInsertNextPoint(fib->m_FiberPolyData->GetPoint(points[j])); + container->GetPointIds()->InsertNextId(id); + } + vNewLines->InsertNextCell(container); } - vNewLines->InsertNextCell(container); - } - // initialize polydata - vNewPolyData->SetPoints(vNewPoints); - vNewPolyData->SetLines(vNewLines); + // initialize polydata + vNewPolyData->SetPoints(vNewPoints); + vNewPolyData->SetLines(vNewLines); - // initialize fiber bundle - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); - return newFib; + // initialize fiber bundle + mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); + return newFib; } // subtract two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib) { - vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); - vtkSmartPointer vNewLines = vtkSmartPointer::New(); - vtkSmartPointer vNewPoints = vtkSmartPointer::New(); - - vtkSmartPointer vLines = m_FiberPolyData->GetLines(); - vLines->InitTraversal(); - - // iterate over current fibers - int numFibers = GetNumFibers(); - for( int i=0; iGetNextCell ( numPoints, points ); - - vtkSmartPointer vLines2 = fib->m_FiberPolyData->GetLines(); - vLines2->InitTraversal(); - int numFibers2 = fib->GetNumFibers(); - bool contained = false; - for( int i2=0; i2GetNextCell ( numPoints2, points2 ); - - // check endpoints - itk::Point point_start = GetItkPoint(m_FiberPolyData->GetPoint(points[0])); - itk::Point point_end = GetItkPoint(m_FiberPolyData->GetPoint(points[numPoints-1])); - itk::Point point2_start = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[0])); - itk::Point point2_end = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[numPoints2-1])); - - if (point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps || - point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps) - { - // further checking ??? - contained = true; - } - } + vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); + vtkSmartPointer vNewLines = vtkSmartPointer::New(); + vtkSmartPointer vNewPoints = vtkSmartPointer::New(); - // add to result because fiber is not subtracted - if (!contained) + vtkSmartPointer vLines = m_FiberPolyData->GetLines(); + vLines->InitTraversal(); + + // iterate over current fibers + int numFibers = GetNumFibers(); + for( int i=0; i container = vtkSmartPointer::New(); - for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); - container->GetPointIds()->InsertNextId(id); - } - vNewLines->InsertNextCell(container); + vtkIdType numPoints(0); + vtkIdType* points(NULL); + vLines->GetNextCell ( numPoints, points ); + + vtkSmartPointer vLines2 = fib->m_FiberPolyData->GetLines(); + vLines2->InitTraversal(); + int numFibers2 = fib->GetNumFibers(); + bool contained = false; + + for( int i2=0; i2GetNextCell ( numPoints2, points2 ); + + // check endpoints + itk::Point point_start = GetItkPoint(m_FiberPolyData->GetPoint(points[0])); + itk::Point point_end = GetItkPoint(m_FiberPolyData->GetPoint(points[numPoints-1])); + itk::Point point2_start = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[0])); + itk::Point point2_end = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[numPoints2-1])); + + if (point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps || + point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps) + { + // further checking ??? + if (numPoints2==numPoints) + contained = true; + } + } + + // add to result because fiber is not subtracted + if (!contained) + { + vtkSmartPointer container = vtkSmartPointer::New(); + for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); + container->GetPointIds()->InsertNextId(id); + } + vNewLines->InsertNextCell(container); + } } - } - if(vNewLines->GetNumberOfCells()==0) - return NULL; - // initialize polydata - vNewPolyData->SetPoints(vNewPoints); - vNewPolyData->SetLines(vNewLines); - - // initialize fiber bundle - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); - return newFib; + if(vNewLines->GetNumberOfCells()==0) + return NULL; + // initialize polydata + vNewPolyData->SetPoints(vNewPoints); + vNewPolyData->SetLines(vNewLines); + + // initialize fiber bundle + mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); + return newFib; } itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) { - itk::Point itkPoint; - itkPoint[0] = point[0]; - itkPoint[1] = point[1]; - itkPoint[2] = point[2]; - return itkPoint; + itk::Point itkPoint; + itkPoint[0] = point[0]; + itkPoint[1] = point[1]; + itkPoint[2] = point[2]; + return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { - if (fiberPD == NULL) - this->m_FiberPolyData = vtkSmartPointer::New(); - else - { - m_FiberPolyData->DeepCopy(fiberPD); - DoColorCodingOrientationBased(); - } + if (fiberPD == NULL) + this->m_FiberPolyData = vtkSmartPointer::New(); + else + { + m_FiberPolyData->DeepCopy(fiberPD); + DoColorCodingOrientationBased(); + } - m_NumFibers = m_FiberPolyData->GetNumberOfLines(); + m_NumFibers = m_FiberPolyData->GetNumberOfLines(); - if (updateGeometry) - UpdateFiberGeometry(); - SetColorCoding(COLORCODING_ORIENTATION_BASED); - GenerateFiberIds(); + if (updateGeometry) + UpdateFiberGeometry(); + SetColorCoding(COLORCODING_ORIENTATION_BASED); + GenerateFiberIds(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() { - return m_FiberPolyData; + return m_FiberPolyData; } void mitk::FiberBundleX::DoColorCodingOrientationBased() { - //===== FOR WRITING A TEST ======================== - // colorT size == tupelComponents * tupelElements - // compare color results - // to cover this code 100% also polydata needed, where colorarray already exists - // + one fiber with exactly 1 point - // + one fiber with 0 points - //================================================= - - - /* make sure that processing colorcoding is only called when necessary */ - if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && - m_FiberPolyData->GetNumberOfPoints() == - m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) - { - // fiberstructure is already colorcoded - MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ; - this->ResetFiberOpacity(); - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - return; - } + //===== FOR WRITING A TEST ======================== + // colorT size == tupelComponents * tupelElements + // compare color results + // to cover this code 100% also polydata needed, where colorarray already exists + // + one fiber with exactly 1 point + // + one fiber with 0 points + //================================================= + + + /* make sure that processing colorcoding is only called when necessary */ + if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && + m_FiberPolyData->GetNumberOfPoints() == + m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) + { + // fiberstructure is already colorcoded + MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ; + this->ResetFiberOpacity(); + this->SetColorCoding(COLORCODING_ORIENTATION_BASED); + return; + } - /* Finally, execute color calculation */ - vtkPoints* extrPoints = NULL; - extrPoints = m_FiberPolyData->GetPoints(); - int numOfPoints = 0; - if (extrPoints!=NULL) - numOfPoints = extrPoints->GetNumberOfPoints(); + /* Finally, execute color calculation */ + vtkPoints* extrPoints = NULL; + extrPoints = m_FiberPolyData->GetPoints(); + int numOfPoints = 0; + if (extrPoints!=NULL) + numOfPoints = extrPoints->GetNumberOfPoints(); - //colors and alpha value for each single point, RGBA = 4 components - unsigned char rgba[4] = {0,0,0,0}; - // int componentSize = sizeof(rgba); - int componentSize = 4; + //colors and alpha value for each single point, RGBA = 4 components + unsigned char rgba[4] = {0,0,0,0}; + // int componentSize = sizeof(rgba); + int componentSize = 4; - vtkSmartPointer colorsT = vtkUnsignedCharArray::New(); - colorsT->Allocate(numOfPoints * componentSize); - colorsT->SetNumberOfComponents(componentSize); - colorsT->SetName(COLORCODING_ORIENTATION_BASED); + vtkSmartPointer colorsT = vtkUnsignedCharArray::New(); + colorsT->Allocate(numOfPoints * componentSize); + colorsT->SetNumberOfComponents(componentSize); + colorsT->SetName(COLORCODING_ORIENTATION_BASED); - /* checkpoint: does polydata contain any fibers */ - int numOfFibers = m_FiberPolyData->GetNumberOfLines(); - if (numOfFibers < 1) { - MITK_DEBUG << "\n ========= Number of Fibers is 0 and below ========= \n"; - return; - } + /* checkpoint: does polydata contain any fibers */ + int numOfFibers = m_FiberPolyData->GetNumberOfLines(); + if (numOfFibers < 1) { + MITK_DEBUG << "\n ========= Number of Fibers is 0 and below ========= \n"; + return; + } - /* extract single fibers of fiberBundle */ - vtkCellArray* fiberList = m_FiberPolyData->GetLines(); - fiberList->InitTraversal(); - for (int fi=0; fiGetLines(); + fiberList->InitTraversal(); + for (int fi=0; fiGetNextCell(pointsPerFiber, idList); + vtkIdType* idList; // contains the point id's of the line + vtkIdType pointsPerFiber; // number of points for current line + fiberList->GetNextCell(pointsPerFiber, idList); - // MITK_DEBUG << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ; + // MITK_DEBUG << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ; - /* single fiber checkpoints: is number of points valid */ - if (pointsPerFiber > 1) - { - /* operate on points of single fiber */ - for (int i=0; i 0) + /* single fiber checkpoints: is number of points valid */ + if (pointsPerFiber > 1) { - /* The color value of the current point is influenced by the previous point and next point. */ - vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); - vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); - vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); + /* operate on points of single fiber */ + for (int i=0; i 0) + { + /* The color value of the current point is influenced by the previous point and next point. */ + vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); + vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); + vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); - vnl_vector_fixed< double, 3 > diff1; - diff1 = currentPntvtk - nextPntvtk; + vnl_vector_fixed< double, 3 > diff1; + diff1 = currentPntvtk - nextPntvtk; - vnl_vector_fixed< double, 3 > diff2; - diff2 = currentPntvtk - prevPntvtk; + vnl_vector_fixed< double, 3 > diff2; + diff2 = currentPntvtk - prevPntvtk; - vnl_vector_fixed< double, 3 > diff; - diff = (diff1 - diff2) / 2.0; - diff.normalize(); + vnl_vector_fixed< double, 3 > diff; + diff = (diff1 - diff2) / 2.0; + diff.normalize(); - rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); - rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); - rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); - rgba[3] = (unsigned char) (255.0); + rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); + rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); + rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); + rgba[3] = (unsigned char) (255.0); - } else if (i==0) { - /* First point has no previous point, therefore only diff1 is taken */ + } else if (i==0) { + /* First point has no previous point, therefore only diff1 is taken */ - vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); - vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); + vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); + vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); - vnl_vector_fixed< double, 3 > diff1; - diff1 = currentPntvtk - nextPntvtk; - diff1.normalize(); + vnl_vector_fixed< double, 3 > diff1; + diff1 = currentPntvtk - nextPntvtk; + diff1.normalize(); - rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); - rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); - rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); - rgba[3] = (unsigned char) (255.0); + rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); + rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); + rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); + rgba[3] = (unsigned char) (255.0); - } else if (i==pointsPerFiber-1) { - /* Last point has no next point, therefore only diff2 is taken */ - vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); - vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); + } else if (i==pointsPerFiber-1) { + /* Last point has no next point, therefore only diff2 is taken */ + vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); + vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); - vnl_vector_fixed< double, 3 > diff2; - diff2 = currentPntvtk - prevPntvtk; - diff2.normalize(); + vnl_vector_fixed< double, 3 > diff2; + diff2 = currentPntvtk - prevPntvtk; + diff2.normalize(); - rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); - rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); - rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); - rgba[3] = (unsigned char) (255.0); + rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); + rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); + rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); + rgba[3] = (unsigned char) (255.0); - } + } - colorsT->InsertTupleValue(idList[i], rgba); + colorsT->InsertTupleValue(idList[i], rgba); - } //end for loop + } //end for loop - } else if (pointsPerFiber == 1) { - /* a single point does not define a fiber (use vertex mechanisms instead */ - continue; - // colorsT->InsertTupleValue(0, rgba); + } else if (pointsPerFiber == 1) { + /* a single point does not define a fiber (use vertex mechanisms instead */ + continue; + // colorsT->InsertTupleValue(0, rgba); - } else { - MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; - continue; + } else { + MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; + continue; - } + } - }//end for loop + }//end for loop - m_FiberPolyData->GetPointData()->AddArray(colorsT); + m_FiberPolyData->GetPointData()->AddArray(colorsT); - /*========================= + /*========================= - this is more relevant for renderer than for fiberbundleX datastructure - think about sourcing this to a explicit method which coordinates colorcoding */ - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - // =========================== + this->SetColorCoding(COLORCODING_ORIENTATION_BASED); + // =========================== - //mini test, shall be ported to MITK TESTINGS! - if (colorsT->GetSize() != numOfPoints*componentSize) - MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; + //mini test, shall be ported to MITK TESTINGS! + if (colorsT->GetSize() != numOfPoints*componentSize) + MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; } void mitk::FiberBundleX::DoColorCodingFaBased() { - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) - return; + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) + return; - this->SetColorCoding(COLORCODING_FA_BASED); - MITK_DEBUG << "FBX: done CC FA based"; - this->GenerateFiberIds(); + this->SetColorCoding(COLORCODING_FA_BASED); + MITK_DEBUG << "FBX: done CC FA based"; + this->GenerateFiberIds(); } void mitk::FiberBundleX::DoUseFaFiberOpacity() { - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) - return; + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) + return; - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 ) - return; + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 ) + return; - vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED); - vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); + vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED); + vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); - for(long i=0; iGetNumberOfTuples(); i++) { - double faValue = FAValArray->GetValue(i); - faValue = faValue * 255.0; - ColorArray->SetComponent(i,3, (unsigned char) faValue ); - } + for(long i=0; iGetNumberOfTuples(); i++) { + double faValue = FAValArray->GetValue(i); + faValue = faValue * 255.0; + ColorArray->SetComponent(i,3, (unsigned char) faValue ); + } - this->SetColorCoding(COLORCODING_ORIENTATION_BASED); - MITK_DEBUG << "FBX: done CC OPACITY"; - this->GenerateFiberIds(); + this->SetColorCoding(COLORCODING_ORIENTATION_BASED); + MITK_DEBUG << "FBX: done CC OPACITY"; + this->GenerateFiberIds(); } void mitk::FiberBundleX::ResetFiberOpacity() { - vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); - for(long i=0; iGetNumberOfTuples(); i++) { - ColorArray->SetComponent(i,3, 255.0 ); - } + vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); + if (ColorArray==NULL) + return; + for(long i=0; iGetNumberOfTuples(); i++) + ColorArray->SetComponent(i,3, 255.0 ); } void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage) { - MITK_DEBUG << "SetFAMap"; - vtkSmartPointer faValues = vtkDoubleArray::New(); - faValues->SetName(COLORCODING_FA_BASED); - faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); - // MITK_DEBUG << faValues->GetNumberOfTuples(); - // MITK_DEBUG << faValues->GetSize(); - - faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); - // MITK_DEBUG << faValues->GetNumberOfTuples(); - // MITK_DEBUG << faValues->GetSize(); - - vtkPoints* pointSet = m_FiberPolyData->GetPoints(); - for(long i=0; iGetNumberOfPoints(); ++i) - { - Point3D px; - px[0] = pointSet->GetPoint(i)[0]; - px[1] = pointSet->GetPoint(i)[1]; - px[2] = pointSet->GetPoint(i)[2]; - double faPixelValue = 1-FAimage->GetPixelValueByWorldCoordinate(px); - // faValues->InsertNextTuple1(faPixelValue); - faValues->InsertValue(i, faPixelValue); - // MITK_DEBUG << faPixelValue; - // MITK_DEBUG << faValues->GetValue(i); - - } - - m_FiberPolyData->GetPointData()->AddArray(faValues); - this->GenerateFiberIds(); - - if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED)) - MITK_DEBUG << "FA VALUE ARRAY SET"; - - // vtkDoubleArray* valueArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(FA_VALUE_ARRAY); - // for(long i=0; iGetNumberOfPoints(); i++) - // { - // MITK_DEBUG << "value at pos "<< i << ": " << valueArray->GetValue(i); - // } + MITK_DEBUG << "SetFAMap"; + vtkSmartPointer faValues = vtkDoubleArray::New(); + faValues->SetName(COLORCODING_FA_BASED); + faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); + // MITK_DEBUG << faValues->GetNumberOfTuples(); + // MITK_DEBUG << faValues->GetSize(); + + faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); + // MITK_DEBUG << faValues->GetNumberOfTuples(); + // MITK_DEBUG << faValues->GetSize(); + + vtkPoints* pointSet = m_FiberPolyData->GetPoints(); + for(long i=0; iGetNumberOfPoints(); ++i) + { + Point3D px; + px[0] = pointSet->GetPoint(i)[0]; + px[1] = pointSet->GetPoint(i)[1]; + px[2] = pointSet->GetPoint(i)[2]; + double faPixelValue = 1-FAimage->GetPixelValueByWorldCoordinate(px); + // faValues->InsertNextTuple1(faPixelValue); + faValues->InsertValue(i, faPixelValue); + // MITK_DEBUG << faPixelValue; + // MITK_DEBUG << faValues->GetValue(i); + + } + + m_FiberPolyData->GetPointData()->AddArray(faValues); + this->GenerateFiberIds(); + + if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED)) + MITK_DEBUG << "FA VALUE ARRAY SET"; + + // vtkDoubleArray* valueArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(FA_VALUE_ARRAY); + // for(long i=0; iGetNumberOfPoints(); i++) + // { + // MITK_DEBUG << "value at pos "<< i << ": " << valueArray->GetValue(i); + // } } void mitk::FiberBundleX::GenerateFiberIds() { - if (m_FiberPolyData == NULL) - return; + if (m_FiberPolyData == NULL) + return; - vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); - idFiberFilter->SetInput(m_FiberPolyData); - idFiberFilter->CellIdsOn(); - // idFiberFilter->PointIdsOn(); // point id's are not needed - idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); - idFiberFilter->FieldDataOn(); - idFiberFilter->Update(); + vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); + idFiberFilter->SetInput(m_FiberPolyData); + idFiberFilter->CellIdsOn(); + // idFiberFilter->PointIdsOn(); // point id's are not needed + idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); + idFiberFilter->FieldDataOn(); + idFiberFilter->Update(); - m_FiberIdDataSet = idFiberFilter->GetOutput(); + m_FiberIdDataSet = idFiberFilter->GetOutput(); - MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); + MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); } -mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(mitk::PlanarFigure::Pointer pf) +mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(mitk::PlanarFigure* pf) { - std::vector tmp = ExtractFiberIdSubset(pf); - if (tmp.size()<=0) - return mitk::FiberBundleX::New(); - vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); - return mitk::FiberBundleX::New(pTmp); + if (pf==NULL) + return NULL; + + std::vector tmp = ExtractFiberIdSubset(pf); + if (tmp.size()<=0) + return mitk::FiberBundleX::New(); + vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); + return mitk::FiberBundleX::New(pTmp); } -std::vector mitk::FiberBundleX::ExtractFiberIdSubset(mitk::PlanarFigure::Pointer pf) +std::vector mitk::FiberBundleX::ExtractFiberIdSubset(mitk::PlanarFigure* pf) { + MITK_DEBUG << "Extracting fibers!"; + // vector which is returned, contains all extracted FiberIds + std::vector FibersInROI; + + if (pf==NULL) + return FibersInROI; + + /* Handle type of planarfigure */ + // if incoming pf is a pfc + mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast(pf); + if (!pfcomp.IsNull()) { + // process requested boolean operation of PFC + switch (pfcomp->getOperationType()) { + case 0: + { + MITK_DEBUG << "AND PROCESSING"; + //AND + //temporarly store results of the child in this vector, we need that to accumulate the + std::vector childResults = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); + MITK_DEBUG << "first roi got fibers in ROI: " << childResults.size(); + MITK_DEBUG << "sorting..."; + std::sort(childResults.begin(), childResults.end()); + MITK_DEBUG << "sorting done"; + std::vector AND_Assamblage(childResults.size()); + //std::vector AND_Assamblage; + fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1); + //AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway + + std::vector::iterator it; + for (int i=1; igetNumberOfChildren(); ++i) + { + std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); + MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size(); + sort(tmpChild.begin(), tmpChild.end()); + + it = std::set_intersection(childResults.begin(), childResults.end(), + tmpChild.begin(), tmpChild.end(), + AND_Assamblage.begin() ); + } + + MITK_DEBUG << "resize Vector"; + long i=0; + while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array + ++i; + } + AND_Assamblage.resize(i); + + MITK_DEBUG << "returning AND vector, size: " << AND_Assamblage.size(); + return AND_Assamblage; + // break; - MITK_DEBUG << "Extracting fibers!"; - // vector which is returned, contains all extracted FiberIds - std::vector FibersInROI; - - /* Handle type of planarfigure */ - // if incoming pf is a pfc - mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast(pf.GetPointer()); - if (!pfcomp.IsNull()) { - // process requested boolean operation of PFC - switch (pfcomp->getOperationType()) { - case 0: - { - MITK_DEBUG << "AND PROCESSING"; - //AND - //temporarly store results of the child in this vector, we need that to accumulate the - std::vector childResults = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); - MITK_DEBUG << "first roi got fibers in ROI: " << childResults.size(); - MITK_DEBUG << "sorting..."; - std::sort(childResults.begin(), childResults.end()); - MITK_DEBUG << "sorting done"; - std::vector AND_Assamblage(childResults.size()); - //std::vector AND_Assamblage; - fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1); - //AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway - - std::vector::iterator it; - for (int i=1; igetNumberOfChildren(); ++i) - { - std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); - MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size(); - sort(tmpChild.begin(), tmpChild.end()); - - it = std::set_intersection(childResults.begin(), childResults.end(), - tmpChild.begin(), tmpChild.end(), - AND_Assamblage.begin() ); - } - - MITK_DEBUG << "resize Vector"; - long i=0; - while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array - ++i; - } - AND_Assamblage.resize(i); - - MITK_DEBUG << "returning AND vector, size: " << AND_Assamblage.size(); - return AND_Assamblage; - // break; + } + case 1: + { + //OR + std::vector OR_Assamblage = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); + std::vector::iterator it; + MITK_DEBUG << OR_Assamblage.size(); + + for (int i=1; igetNumberOfChildren(); ++i) { + it = OR_Assamblage.end(); + std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); + OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end()); + MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size(); + } + + sort(OR_Assamblage.begin(), OR_Assamblage.end()); + it = unique(OR_Assamblage.begin(), OR_Assamblage.end()); + OR_Assamblage.resize( it - OR_Assamblage.begin() ); + MITK_DEBUG << "returning OR vector, size: " << OR_Assamblage.size(); + + return OR_Assamblage; + } + case 2: + { + //NOT + //get IDs of all fibers + std::vector childResults; + childResults.reserve(this->GetNumFibers()); + vtkSmartPointer idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY); + MITK_DEBUG << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples(); + for(long i=0; iGetNumFibers(); i++) + { + MITK_DEBUG << "i: " << i << " idset: " << idSet->GetTuple(i)[0]; + childResults.push_back(idSet->GetTuple(i)[0]); + } + + std::sort(childResults.begin(), childResults.end()); + std::vector NOT_Assamblage(childResults.size()); + //fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber! + fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1); + std::vector::iterator it; + + for (long i=0; igetNumberOfChildren(); ++i) + { + std::vector tmpChild = ExtractFiberIdSubset(pfcomp->getChildAt(i)); + sort(tmpChild.begin(), tmpChild.end()); + + it = std::set_difference(childResults.begin(), childResults.end(), + tmpChild.begin(), tmpChild.end(), + NOT_Assamblage.begin() ); + + } + + MITK_DEBUG << "resize Vector"; + long i=0; + while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array + ++i; + } + NOT_Assamblage.resize(i); + + return NOT_Assamblage; + } + default: + MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ; + break; + } } - case 1: - { - //OR - std::vector OR_Assamblage = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); - std::vector::iterator it; - MITK_DEBUG << OR_Assamblage.size(); - - for (int i=1; igetNumberOfChildren(); ++i) { - it = OR_Assamblage.end(); - std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); - OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end()); - MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size(); - } - - sort(OR_Assamblage.begin(), OR_Assamblage.end()); - it = unique(OR_Assamblage.begin(), OR_Assamblage.end()); - OR_Assamblage.resize( it - OR_Assamblage.begin() ); - MITK_DEBUG << "returning OR vector, size: " << OR_Assamblage.size(); - - return OR_Assamblage; - } - case 2: + else { - //NOT - //get IDs of all fibers - std::vector childResults; - childResults.reserve(this->GetNumFibers()); - vtkSmartPointer idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY); - MITK_DEBUG << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples(); - for(long i=0; iGetNumFibers(); i++) - { - MITK_DEBUG << "i: " << i << " idset: " << idSet->GetTuple(i)[0]; - childResults.push_back(idSet->GetTuple(i)[0]); - } - - std::sort(childResults.begin(), childResults.end()); - std::vector NOT_Assamblage(childResults.size()); - //fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber! - fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1); - std::vector::iterator it; - - for (long i=0; igetNumberOfChildren(); ++i) - { - std::vector tmpChild = ExtractFiberIdSubset(pfcomp->getChildAt(i)); - sort(tmpChild.begin(), tmpChild.end()); - - it = std::set_difference(childResults.begin(), childResults.end(), - tmpChild.begin(), tmpChild.end(), - NOT_Assamblage.begin() ); - - } - - MITK_DEBUG << "resize Vector"; - long i=0; - while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array - ++i; - } - NOT_Assamblage.resize(i); - - return NOT_Assamblage; - } - default: - MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ; - break; - - } - } - else - { - mitk::Geometry2D::ConstPointer pfgeometry = pf->GetGeometry2D(); - const mitk::PlaneGeometry* planeGeometry = dynamic_cast (pfgeometry.GetPointer()); - Vector3D planeNormal = planeGeometry->GetNormal(); - planeNormal.Normalize(); - Point3D planeOrigin = planeGeometry->GetOrigin(); - - MITK_DEBUG << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl; - MITK_DEBUG << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl; - - std::vector PointsOnPlane; // contains all pointIds which are crossing the cutting plane - std::vector PointsInROI; // based on PointsOnPlane, all ROI relevant point IDs are stored here - - /* Define cutting plane by ROI (PlanarFigure) */ - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); - plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); - - //same plane but opposite normal direction. so point cloud will be reduced -> better performance - // vtkSmartPointer planeR = vtkSmartPointer::New(); - - //define new origin along the normal but close to the original one - // OriginNew = OriginOld + 1*Normal - // Vector3D extendedNormal; - // int multiplyFactor = 1; - // extendedNormal[0] = planeNormal[0] * multiplyFactor; - // extendedNormal[1] = planeNormal[1] * multiplyFactor; - // extendedNormal[2] = planeNormal[2] * multiplyFactor; - // Point3D RplaneOrigin = planeOrigin - extendedNormal; - // planeR->SetOrigin(RplaneOrigin[0],RplaneOrigin[1],RplaneOrigin[2]); - // planeR->SetNormal(-planeNormal[0],-planeNormal[1],-planeNormal[2]); - // MITK_DEBUG << "RPlaneOrigin: " << RplaneOrigin[0] << " | " << RplaneOrigin[1] - // << " | " << RplaneOrigin[2]; - - /* get all points/fibers cutting the plane */ - MITK_DEBUG << "start clipping"; - vtkSmartPointer clipper = vtkSmartPointer::New(); - clipper->SetInput(m_FiberIdDataSet); - clipper->SetClipFunction(plane); - clipper->GenerateClipScalarsOn(); - clipper->GenerateClippedOutputOn(); - vtkSmartPointer clipperout = clipper->GetClippedOutput(); - MITK_DEBUG << "end clipping"; - - /* for some reason clipperoutput is not initialized for futher processing + mitk::Geometry2D::ConstPointer pfgeometry = pf->GetGeometry2D(); + const mitk::PlaneGeometry* planeGeometry = dynamic_cast (pfgeometry.GetPointer()); + Vector3D planeNormal = planeGeometry->GetNormal(); + planeNormal.Normalize(); + Point3D planeOrigin = planeGeometry->GetOrigin(); + + MITK_DEBUG << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl; + MITK_DEBUG << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl; + + std::vector PointsOnPlane; // contains all pointIds which are crossing the cutting plane + std::vector PointsInROI; // based on PointsOnPlane, all ROI relevant point IDs are stored here + + /* Define cutting plane by ROI (PlanarFigure) */ + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); + plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); + + //same plane but opposite normal direction. so point cloud will be reduced -> better performance + // vtkSmartPointer planeR = vtkSmartPointer::New(); + + //define new origin along the normal but close to the original one + // OriginNew = OriginOld + 1*Normal + // Vector3D extendedNormal; + // int multiplyFactor = 1; + // extendedNormal[0] = planeNormal[0] * multiplyFactor; + // extendedNormal[1] = planeNormal[1] * multiplyFactor; + // extendedNormal[2] = planeNormal[2] * multiplyFactor; + // Point3D RplaneOrigin = planeOrigin - extendedNormal; + // planeR->SetOrigin(RplaneOrigin[0],RplaneOrigin[1],RplaneOrigin[2]); + // planeR->SetNormal(-planeNormal[0],-planeNormal[1],-planeNormal[2]); + // MITK_DEBUG << "RPlaneOrigin: " << RplaneOrigin[0] << " | " << RplaneOrigin[1] + // << " | " << RplaneOrigin[2]; + + /* get all points/fibers cutting the plane */ + MITK_DEBUG << "start clipping"; + vtkSmartPointer clipper = vtkSmartPointer::New(); + clipper->SetInput(m_FiberIdDataSet); + clipper->SetClipFunction(plane); + clipper->GenerateClipScalarsOn(); + clipper->GenerateClippedOutputOn(); + vtkSmartPointer clipperout = clipper->GetClippedOutput(); + MITK_DEBUG << "end clipping"; + + /* for some reason clipperoutput is not initialized for futher processing * so far only writing out clipped polydata provides requested */ - // MITK_DEBUG << "writing clipper output"; - // vtkSmartPointer writerC = vtkSmartPointer::New(); - // writerC->SetInput(clipperout1); - // writerC->SetFileName("/vtkOutput/Clipping.vtk"); - // writerC->SetFileTypeToASCII(); - // writerC->Write(); - // MITK_DEBUG << "writing done"; - - MITK_DEBUG << "init and update clipperoutput"; - clipperout->GetPointData()->Initialize(); - clipperout->Update(); - MITK_DEBUG << "init and update clipperoutput completed"; - - // MITK_DEBUG << "start clippingRecursive"; - // vtkSmartPointer Rclipper = vtkSmartPointer::New(); - // Rclipper->SetInput(clipperout1); - // Rclipper->SetClipFunction(planeR); - // Rclipper->GenerateClipScalarsOn(); - // Rclipper->GenerateClippedOutputOn(); - // vtkSmartPointer clipperout = Rclipper->GetClippedOutput(); - // MITK_DEBUG << "end clipping recursive"; - - // MITK_DEBUG << "writing clipper output 2"; - // vtkSmartPointer writerC1 = vtkSmartPointer::New(); - // writerC1->SetInput(clipperout); - // writerC1->SetFileName("/vtkOutput/RClipping.vtk"); - // writerC1->SetFileTypeToASCII(); - // writerC1->Write(); - // MITK_DEBUG << "init and update clipperoutput"; - // clipperout->GetPointData()->Initialize(); - // clipperout->Update(); - // MITK_DEBUG << "init and update clipperoutput completed"; - - MITK_DEBUG << "STEP 1: find all points which have distance 0 to the given plane"; - /*======STEP 1====== + // MITK_DEBUG << "writing clipper output"; + // vtkSmartPointer writerC = vtkSmartPointer::New(); + // writerC->SetInput(clipperout1); + // writerC->SetFileName("/vtkOutput/Clipping.vtk"); + // writerC->SetFileTypeToASCII(); + // writerC->Write(); + // MITK_DEBUG << "writing done"; + + MITK_DEBUG << "init and update clipperoutput"; + clipperout->GetPointData()->Initialize(); + clipperout->Update(); + MITK_DEBUG << "init and update clipperoutput completed"; + + // MITK_DEBUG << "start clippingRecursive"; + // vtkSmartPointer Rclipper = vtkSmartPointer::New(); + // Rclipper->SetInput(clipperout1); + // Rclipper->SetClipFunction(planeR); + // Rclipper->GenerateClipScalarsOn(); + // Rclipper->GenerateClippedOutputOn(); + // vtkSmartPointer clipperout = Rclipper->GetClippedOutput(); + // MITK_DEBUG << "end clipping recursive"; + + // MITK_DEBUG << "writing clipper output 2"; + // vtkSmartPointer writerC1 = vtkSmartPointer::New(); + // writerC1->SetInput(clipperout); + // writerC1->SetFileName("/vtkOutput/RClipping.vtk"); + // writerC1->SetFileTypeToASCII(); + // writerC1->Write(); + // MITK_DEBUG << "init and update clipperoutput"; + // clipperout->GetPointData()->Initialize(); + // clipperout->Update(); + // MITK_DEBUG << "init and update clipperoutput completed"; + + MITK_DEBUG << "STEP 1: find all points which have distance 0 to the given plane"; + /*======STEP 1====== * extract all points, which are crossing the plane */ - // Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index - vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); - vtkIdType sizeOfList = distanceList->GetNumberOfTuples(); - PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then! + // Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index + vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); + vtkIdType sizeOfList = distanceList->GetNumberOfTuples(); + PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then! * size of list can be optimized by reducing allocation, but be aware of iterator and vector size*/ - for (int i=0; iGetTuple(i); + for (int i=0; iGetTuple(i); - // check if point is on plane. - // 0.01 due to some approximation errors when calculating distance - if (distance[0] >= -0.01 && distance[0] <= 0.01) - PointsOnPlane.push_back(i); - } + // check if point is on plane. + // 0.01 due to some approximation errors when calculating distance + if (distance[0] >= -0.01 && distance[0] <= 0.01) + PointsOnPlane.push_back(i); + } - // DEBUG print out all interesting points, stop where array starts with value -1. after -1 no more interesting idx are set! - // std::vector::iterator rit = PointsOnPlane.begin(); - // while (rit != PointsOnPlane.end() ) { - // std::cout << "interesting point: " << *rit << " coord: " << clipperout->GetPoint(*rit)[0] << " | " << clipperout->GetPoint(*rit)[1] << " | " << clipperout->GetPoint(*rit)[2] << endl; - // rit++; - // } + // DEBUG print out all interesting points, stop where array starts with value -1. after -1 no more interesting idx are set! + // std::vector::iterator rit = PointsOnPlane.begin(); + // while (rit != PointsOnPlane.end() ) { + // std::cout << "interesting point: " << *rit << " coord: " << clipperout->GetPoint(*rit)[0] << " | " << clipperout->GetPoint(*rit)[1] << " | " << clipperout->GetPoint(*rit)[2] << endl; + // rit++; + // } - MITK_DEBUG << "Num Of points on plane: " << PointsOnPlane.size(); + MITK_DEBUG << "Num Of points on plane: " << PointsOnPlane.size(); - MITK_DEBUG << "Step 2: extract Interesting points with respect to given extraction planarFigure"; + MITK_DEBUG << "Step 2: extract Interesting points with respect to given extraction planarFigure"; - PointsInROI.reserve(PointsOnPlane.size()); - /*=======STEP 2===== + PointsInROI.reserve(PointsOnPlane.size()); + /*=======STEP 2===== * extract ROI relevant pointIds */ - mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); - mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); - if ( pf->GetNameOfClass() == circleName->GetNameOfClass() ) - { - //calculate circle radius - mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint - mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint - - double distPF = V1w.EuclideanDistanceTo(V2w); - - for (int i=0; iGetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) + - (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) + - (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ; - - if( XdistPnt <= distPF) - PointsInROI.push_back(PointsOnPlane[i]); - } - } - else if ( pf->GetNameOfClass() == polyName->GetNameOfClass() ) - { - //create vtkPolygon using controlpoints from planarFigure polygon - vtkSmartPointer polygonVtk = vtkPolygon::New(); - - //get the control points from pf and insert them to vtkPolygon - unsigned int nrCtrlPnts = pf->GetNumberOfControlPoints(); - - for (int i=0; iGetPoints()->InsertNextPoint((double)pf->GetWorldControlPoint(i)[0], (double)pf->GetWorldControlPoint(i)[1], (double)pf->GetWorldControlPoint(i)[2] ); - } - - //prepare everything for using pointInPolygon function - double n[3]; - polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), - static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); - - double bounds[6]; - polygonVtk->GetPoints()->GetBounds(bounds); - - for (int i=0; iGetPoint(PointsOnPlane[i])[0], clipperout->GetPoint(PointsOnPlane[i])[1], clipperout->GetPoint(PointsOnPlane[i])[2]}; - int isInPolygon = polygonVtk->PointInPolygon(checkIn, polygonVtk->GetPoints()->GetNumberOfPoints() - , static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); - if( isInPolygon ) - PointsInROI.push_back(PointsOnPlane[i]); - } - } + mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); + mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); + if ( pf->GetNameOfClass() == circleName->GetNameOfClass() ) + { + //calculate circle radius + mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint + mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint + + double distPF = V1w.EuclideanDistanceTo(V2w); + + for (int i=0; iGetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) + + (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) + + (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ; + + if( XdistPnt <= distPF) + PointsInROI.push_back(PointsOnPlane[i]); + } + } + else if ( pf->GetNameOfClass() == polyName->GetNameOfClass() ) + { + //create vtkPolygon using controlpoints from planarFigure polygon + vtkSmartPointer polygonVtk = vtkPolygon::New(); + + //get the control points from pf and insert them to vtkPolygon + unsigned int nrCtrlPnts = pf->GetNumberOfControlPoints(); + + for (int i=0; iGetPoints()->InsertNextPoint((double)pf->GetWorldControlPoint(i)[0], (double)pf->GetWorldControlPoint(i)[1], (double)pf->GetWorldControlPoint(i)[2] ); + } + + //prepare everything for using pointInPolygon function + double n[3]; + polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), + static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); + + double bounds[6]; + polygonVtk->GetPoints()->GetBounds(bounds); + + for (int i=0; iGetPoint(PointsOnPlane[i])[0], clipperout->GetPoint(PointsOnPlane[i])[1], clipperout->GetPoint(PointsOnPlane[i])[2]}; + int isInPolygon = polygonVtk->PointInPolygon(checkIn, polygonVtk->GetPoints()->GetNumberOfPoints() + , static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); + if( isInPolygon ) + PointsInROI.push_back(PointsOnPlane[i]); + } + } - MITK_DEBUG << "Step3: Identify fibers"; - // we need to access the fiberId Array, so make sure that this array is available - if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) - { - MITK_DEBUG << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()"; - return FibersInROI; // FibersInRoi is empty then - } - if (PointsInROI.size()<=0) - return FibersInROI; + MITK_DEBUG << "Step3: Identify fibers"; + // we need to access the fiberId Array, so make sure that this array is available + if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) + { + MITK_DEBUG << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()"; + return FibersInROI; // FibersInRoi is empty then + } + if (PointsInROI.size()<=0) + return FibersInROI; - // prepare a structure where each point id is represented as an indexId. - // vector looks like: | pntId | fiberIdx | - std::vector< long > pointindexFiberMap; + // prepare a structure where each point id is represented as an indexId. + // vector looks like: | pntId | fiberIdx | + std::vector< long > pointindexFiberMap; - // walk through the whole subline section and create an vector sorted by point index - vtkCellArray *clipperlines = clipperout->GetLines(); - clipperlines->InitTraversal(); - long numOfLineCells = clipperlines->GetNumberOfCells(); - long numofClippedPoints = clipperout->GetNumberOfPoints(); - pointindexFiberMap.resize(numofClippedPoints); + // walk through the whole subline section and create an vector sorted by point index + vtkCellArray *clipperlines = clipperout->GetLines(); + clipperlines->InitTraversal(); + long numOfLineCells = clipperlines->GetNumberOfCells(); + long numofClippedPoints = clipperout->GetNumberOfPoints(); + pointindexFiberMap.resize(numofClippedPoints); - //prepare resulting vector - FibersInROI.reserve(PointsInROI.size()); + //prepare resulting vector + FibersInROI.reserve(PointsInROI.size()); - MITK_DEBUG << "\n===== Pointindex based structure initialized ======\n"; + MITK_DEBUG << "\n===== Pointindex based structure initialized ======\n"; - // go through resulting "sub"lines which are stored as cells, "i" corresponds to current line id. - for (int i=0, ic=0 ; iGetCell(ic, npts, pts); + vtkIdType npts; + vtkIdType *pts; + clipperlines->GetCell(ic, npts, pts); - // go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46 - for (long j=0; jGetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j]; - pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; - // MITK_DEBUG << "in array: " << pointindexFiberMap[ pts[j] ]; - } + // go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46 + for (long j=0; jGetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j]; + pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; + // MITK_DEBUG << "in array: " << pointindexFiberMap[ pts[j] ]; + } - } + } - MITK_DEBUG << "\n===== Pointindex based structure finalized ======\n"; + MITK_DEBUG << "\n===== Pointindex based structure finalized ======\n"; - // get all Points in ROI with according fiberID - for (long k = 0; k < PointsInROI.size(); k++) - { - //MITK_DEBUG << "point " << PointsInROI[k] << " belongs to fiber " << pointindexFiberMap[ PointsInROI[k] ]; - if (pointindexFiberMap[ PointsInROI[k] ]<=GetNumFibers() && pointindexFiberMap[ PointsInROI[k] ]>=0) - FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]); - else - MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected"; - } + // get all Points in ROI with according fiberID + for (long k = 0; k < PointsInROI.size(); k++) + { + //MITK_DEBUG << "point " << PointsInROI[k] << " belongs to fiber " << pointindexFiberMap[ PointsInROI[k] ]; + if (pointindexFiberMap[ PointsInROI[k] ]<=GetNumFibers() && pointindexFiberMap[ PointsInROI[k] ]>=0) + FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]); + else + MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected"; + } - } + } - // detecting fiberId duplicates - MITK_DEBUG << "check for duplicates"; + // detecting fiberId duplicates + MITK_DEBUG << "check for duplicates"; - sort(FibersInROI.begin(), FibersInROI.end()); - bool hasDuplicats = false; - for(long i=0; i::iterator it; - it = unique (FibersInROI.begin(), FibersInROI.end()); - FibersInROI.resize( it - FibersInROI.begin() ); - } + if(hasDuplicats) + { + std::vector::iterator it; + it = unique (FibersInROI.begin(), FibersInROI.end()); + FibersInROI.resize( it - FibersInROI.begin() ); + } - return FibersInROI; + return FibersInROI; } void mitk::FiberBundleX::UpdateFiberGeometry() { - if (m_NumFibers<=0) // no fibers present; apply default geometry - { - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - geometry->SetImageGeometry(true); - float b[] = {0, 1, 0, 1, 0, 1}; - geometry->SetFloatBounds(b); - SetGeometry(geometry); - return; - } - float min = itk::NumericTraits::NonpositiveMin(); - float max = itk::NumericTraits::max(); - float b[] = {max, min, max, min, max, min}; - - vtkCellArray* cells = m_FiberPolyData->GetLines(); - cells->InitTraversal(); - for (int i=0; iGetNumberOfCells(); i++) - { - vtkCell* cell = m_FiberPolyData->GetCell(i); - int p = cell->GetNumberOfPoints(); - vtkPoints* points = cell->GetPoints(); - for (int j=0; jSetImageGeometry(true); + float b[] = {0, 1, 0, 1, 0, 1}; + geometry->SetFloatBounds(b); + SetGeometry(geometry); + return; + } + float min = itk::NumericTraits::NonpositiveMin(); + float max = itk::NumericTraits::max(); + float b[] = {max, min, max, min, max, min}; + + vtkCellArray* cells = m_FiberPolyData->GetLines(); + cells->InitTraversal(); + for (int i=0; iGetNumberOfCells(); i++) { - double p[3]; - points->GetPoint(j, p); - - if (p[0]b[1]) - b[1]=p[0]; - - if (p[1]b[3]) - b[3]=p[1]; - - if (p[2]b[5]) - b[5]=p[2]; + vtkCell* cell = m_FiberPolyData->GetCell(i); + int p = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + for (int j=0; jGetPoint(j, p); + + if (p[0]b[1]) + b[1]=p[0]; + + if (p[1]b[3]) + b[3]=p[1]; + + if (p[2]b[5]) + b[5]=p[2]; + } } - } - // provide some border margin - for(int i=0; i<=4; i+=2) - b[i] -=10; - for(int i=1; i<=5; i+=2) - b[i] +=10; - - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); - geometry->SetFloatBounds(b); - this->SetGeometry(geometry); + // provide some border margin + for(int i=0; i<=4; i+=2) + b[i] -=10; + for(int i=1; i<=5; i+=2) + b[i] +=10; + + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + geometry->SetFloatBounds(b); + this->SetGeometry(geometry); } QStringList mitk::FiberBundleX::GetAvailableColorCodings() { - QStringList availableColorCodings; - int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays(); - for(int i=0; iGetPointData()->GetArrayName(i)); - } - - //this controlstructure shall be implemented by the calling method - if (availableColorCodings.isEmpty()) - MITK_DEBUG << "no colorcodings available in fiberbundleX"; - - // for(int i=0; iGetPointData()->GetNumberOfArrays(); + for(int i=0; iGetPointData()->GetArrayName(i)); + } + + //this controlstructure shall be implemented by the calling method + if (availableColorCodings.isEmpty()) + MITK_DEBUG << "no colorcodings available in fiberbundleX"; + + // for(int i=0; im_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; + if( strcmp (COLORCODING_ORIENTATION_BASED,requestedColorCoding) == 0 ) { + this->m_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; - } else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { - this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED; + } else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { + this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED; - } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { - this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; + } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { + this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; - } else { - MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; - this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers - } + } else { + MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; + this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers + } } void mitk::FiberBundleX::DoFiberSmoothing(int pointsPerCm) { - vtkSmartPointer vtkSmoothPoints = vtkPoints::New(); //in smoothpoints the interpolated points representing a fiber are stored. - - //in vtkcells all polylines are stored, actually all id's of them are stored - vtkSmartPointer vtkSmoothCells = vtkCellArray::New(); //cellcontainer for smoothed lines + vtkSmartPointer vtkSmoothPoints = vtkPoints::New(); //in smoothpoints the interpolated points representing a fiber are stored. - vtkSmartPointer vLines = m_FiberPolyData->GetLines(); - vLines->InitTraversal(); - vtkIdType pointHelperCnt = 0; - for (int i=0; iGetNextCell ( numPoints, pointIds ); + //in vtkcells all polylines are stored, actually all id's of them are stored + vtkSmartPointer vtkSmoothCells = vtkCellArray::New(); //cellcontainer for smoothed lines - vtkSmartPointer points = vtkSmartPointer::New(); - float length = 0; - itk::Point lastP; - for (int j=0; jGetPoint(pointIds[j]); - points->InsertNextPoint(p); - if (j>0) - length += sqrt(pow(p[0]-lastP[0], 2)+pow(p[1]-lastP[1], 2)+pow(p[2]-lastP[2], 2)); - lastP[0] = p[0]; - lastP[1] = p[1]; - lastP[2] = p[2]; - } - length /=10; - int sampling = pointsPerCm*length; - - /////PROCESS POLYLINE SMOOTHING///// - vtkSmartPointer xSpline = vtkKochanekSpline::New(); - vtkSmartPointer ySpline = vtkKochanekSpline::New(); - vtkSmartPointer zSpline = vtkKochanekSpline::New(); - - vtkSmartPointer spline = vtkParametricSpline::New(); - spline->SetXSpline(xSpline); - spline->SetYSpline(ySpline); - spline->SetZSpline(zSpline); - spline->SetPoints(points); - - vtkSmartPointer functionSource = vtkParametricFunctionSource::New(); - functionSource->SetParametricFunction(spline); - functionSource->SetUResolution(sampling); - functionSource->SetVResolution(sampling); - functionSource->SetWResolution(sampling); - functionSource->Update(); - - vtkPolyData* outputFunction = functionSource->GetOutput(); - vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber - - vtkSmartPointer smoothLine = vtkPolyLine::New(); - smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); - - for (int j=0; jGetNumberOfPoints(); j++) + vtkSmartPointer vLines = m_FiberPolyData->GetLines(); + vLines->InitTraversal(); + vtkIdType pointHelperCnt = 0; + for (int i=0; iGetPointIds()->SetId(j, j+pointHelperCnt); - vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); + vtkIdType numPoints(0); + vtkIdType* pointIds(NULL); + vLines->GetNextCell ( numPoints, pointIds ); + + vtkSmartPointer points = vtkSmartPointer::New(); + float length = 0; + itk::Point lastP; + for (int j=0; jGetPoint(pointIds[j]); + points->InsertNextPoint(p); + if (j>0) + length += sqrt(pow(p[0]-lastP[0], 2)+pow(p[1]-lastP[1], 2)+pow(p[2]-lastP[2], 2)); + lastP[0] = p[0]; + lastP[1] = p[1]; + lastP[2] = p[2]; + } + length /=10; + int sampling = pointsPerCm*length; + + /////PROCESS POLYLINE SMOOTHING///// + vtkSmartPointer xSpline = vtkKochanekSpline::New(); + vtkSmartPointer ySpline = vtkKochanekSpline::New(); + vtkSmartPointer zSpline = vtkKochanekSpline::New(); + + vtkSmartPointer spline = vtkParametricSpline::New(); + spline->SetXSpline(xSpline); + spline->SetYSpline(ySpline); + spline->SetZSpline(zSpline); + spline->SetPoints(points); + + vtkSmartPointer functionSource = vtkParametricFunctionSource::New(); + functionSource->SetParametricFunction(spline); + functionSource->SetUResolution(sampling); + functionSource->SetVResolution(sampling); + functionSource->SetWResolution(sampling); + functionSource->Update(); + + vtkPolyData* outputFunction = functionSource->GetOutput(); + vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber + + vtkSmartPointer smoothLine = vtkPolyLine::New(); + smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); + + for (int j=0; jGetNumberOfPoints(); j++) + { + smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); + vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); + } + vtkSmoothCells->InsertNextCell(smoothLine); + pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } - vtkSmoothCells->InsertNextCell(smoothLine); - pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); - } - - m_FiberPolyData = vtkSmartPointer::New(); - m_FiberPolyData->SetPoints(vtkSmoothPoints); - m_FiberPolyData->SetLines(vtkSmoothCells); - UpdateColorCoding(); - UpdateFiberGeometry(); + + m_FiberPolyData = vtkSmartPointer::New(); + m_FiberPolyData->SetPoints(vtkSmoothPoints); + m_FiberPolyData->SetLines(vtkSmoothCells); + UpdateColorCoding(); + UpdateFiberGeometry(); } // Resample fiber to get equidistant points void mitk::FiberBundleX::ResampleFibers(float pointDistance) { - vtkSmartPointer newPoly = vtkSmartPointer::New(); - vtkSmartPointer newCellArray = vtkSmartPointer::New(); - vtkSmartPointer newPoints = vtkSmartPointer::New(); + vtkSmartPointer newPoly = vtkSmartPointer::New(); + vtkSmartPointer newCellArray = vtkSmartPointer::New(); + vtkSmartPointer newPoints = vtkSmartPointer::New(); - vtkSmartPointer vLines = m_FiberPolyData->GetLines(); - vLines->InitTraversal(); - int numberOfLines = m_NumFibers; + vtkSmartPointer vLines = m_FiberPolyData->GetLines(); + vLines->InitTraversal(); + int numberOfLines = m_NumFibers; - for (int i=0; iGetNextCell ( numPoints, points ); + for (int i=0; iGetNextCell ( numPoints, points ); - vtkSmartPointer container = vtkSmartPointer::New(); + vtkSmartPointer container = vtkSmartPointer::New(); - double* point = m_FiberPolyData->GetPoint(points[0]); - vtkIdType pointId = newPoints->InsertNextPoint(point); - container->GetPointIds()->InsertNextId(pointId); + double* point = m_FiberPolyData->GetPoint(points[0]); + vtkIdType pointId = newPoints->InsertNextPoint(point); + container->GetPointIds()->InsertNextId(pointId); - float dtau = 0; - int cur_p = 1; - itk::Vector dR; - float normdR = 0; + float dtau = 0; + int cur_p = 1; + itk::Vector dR; + float normdR = 0; - for (;;) - { - while (dtau <= pointDistance && cur_p < numPoints) - { - itk::Vector v1; - point = m_FiberPolyData->GetPoint(points[cur_p-1]); - v1[0] = point[0]; - v1[1] = point[1]; - v1[2] = point[2]; - itk::Vector v2; - point = m_FiberPolyData->GetPoint(points[cur_p]); - v2[0] = point[0]; - v2[1] = point[1]; - v2[2] = point[2]; - - dR = v2 - v1; - normdR = std::sqrt(dR.GetSquaredNorm()); - dtau += normdR; - cur_p++; - } - - if (dtau >= pointDistance) - { - itk::Vector v1; - point = m_FiberPolyData->GetPoint(points[cur_p-1]); - v1[0] = point[0]; - v1[1] = point[1]; - v1[2] = point[2]; - - itk::Vector v2 = v1 - dR*( (dtau-pointDistance)/normdR ); - pointId = newPoints->InsertNextPoint(v2.GetDataPointer()); - container->GetPointIds()->InsertNextId(pointId); - } - else - { - point = m_FiberPolyData->GetPoint(points[numPoints-1]); - pointId = newPoints->InsertNextPoint(point); - container->GetPointIds()->InsertNextId(pointId); - break; - } - dtau = dtau-pointDistance; - } + for (;;) + { + while (dtau <= pointDistance && cur_p < numPoints) + { + itk::Vector v1; + point = m_FiberPolyData->GetPoint(points[cur_p-1]); + v1[0] = point[0]; + v1[1] = point[1]; + v1[2] = point[2]; + itk::Vector v2; + point = m_FiberPolyData->GetPoint(points[cur_p]); + v2[0] = point[0]; + v2[1] = point[1]; + v2[2] = point[2]; + + dR = v2 - v1; + normdR = std::sqrt(dR.GetSquaredNorm()); + dtau += normdR; + cur_p++; + } + + if (dtau >= pointDistance) + { + itk::Vector v1; + point = m_FiberPolyData->GetPoint(points[cur_p-1]); + v1[0] = point[0]; + v1[1] = point[1]; + v1[2] = point[2]; + + itk::Vector v2 = v1 - dR*( (dtau-pointDistance)/normdR ); + pointId = newPoints->InsertNextPoint(v2.GetDataPointer()); + container->GetPointIds()->InsertNextId(pointId); + } + else + { + point = m_FiberPolyData->GetPoint(points[numPoints-1]); + pointId = newPoints->InsertNextPoint(point); + container->GetPointIds()->InsertNextId(pointId); + break; + } + dtau = dtau-pointDistance; + } - newCellArray->InsertNextCell(container); - } + newCellArray->InsertNextCell(container); + } - newPoly->SetPoints(newPoints); - newPoly->SetLines(newCellArray); - m_FiberPolyData = newPoly; - UpdateFiberGeometry(); - UpdateColorCoding(); + newPoly->SetPoints(newPoints); + newPoly->SetLines(newCellArray); + m_FiberPolyData = newPoly; + UpdateFiberGeometry(); + UpdateColorCoding(); } // reapply selected colorcoding in case polydata structure has changed void mitk::FiberBundleX::UpdateColorCoding() { - char* cc = GetCurrentColorCoding(); + char* cc = GetCurrentColorCoding(); + + if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 ) + DoColorCodingOrientationBased(); + else if( strcmp (COLORCODING_FA_BASED,cc) == 0 ) + DoColorCodingFaBased(); +} + +// reapply selected colorcoding in case polydata structure has changed +bool mitk::FiberBundleX::Equals(mitk::FiberBundleX* fib) +{ + if (fib==NULL) + return false; + + mitk::FiberBundleX::Pointer tempFib = this->SubtractBundle(fib); + mitk::FiberBundleX::Pointer tempFib2 = fib->SubtractBundle(this); + + if (tempFib.IsNull() && tempFib2.IsNull()) + return true; - if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 ) - DoColorCodingOrientationBased(); - else if( strcmp (COLORCODING_FA_BASED,cc) == 0 ) - DoColorCodingFaBased(); + return false; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { - return false; + return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { - return true; + return true; } void mitk::FiberBundleX::SetRequestedRegion( itk::DataObject *data ) { } diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h index 431af738ad..a6a6f5e76f 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h @@ -1,121 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_FiberBundleX_H #define _MITK_FiberBundleX_H //includes for MITK datastructure #include #include "MitkDiffusionImagingExports.h" #include //includes storing fiberdata #include //may be replaced by class precompile argument #include // may be replaced by class #include // my be replaced by class #include #include #include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MitkDiffusionImaging_EXPORT FiberBundleX : public BaseData { public: // fiber colorcodings static const char* COLORCODING_ORIENTATION_BASED; static const char* COLORCODING_FA_BASED; static const char* COLORCODING_CUSTOM; static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion( itk::DataObject *data ); mitkClassMacro( FiberBundleX, BaseData ) itkNewMacro( Self ) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // colorcoding related methods void SetColorCoding(const char*); void SetFAMap(mitk::Image::Pointer); void DoColorCodingOrientationBased(); void DoColorCodingFaBased(); void DoUseFaFiberOpacity(); void ResetFiberOpacity(); // fiber smoothing/resampling void ResampleFibers(float pointDistance = 1); void DoFiberSmoothing(int pointsPerCm); // add/subtract fibers - mitk::FiberBundleX::Pointer AddBundle(mitk::FiberBundleX* fib); - mitk::FiberBundleX::Pointer SubtractBundle(mitk::FiberBundleX* fib); + FiberBundleX::Pointer AddBundle(FiberBundleX* fib); + FiberBundleX::Pointer SubtractBundle(FiberBundleX* fib); // fiber subset extraction - mitk::FiberBundleX::Pointer ExtractFiberSubset(mitk::PlanarFigure::Pointer pf); - std::vector ExtractFiberIdSubset(mitk::PlanarFigure::Pointer pf); + FiberBundleX::Pointer ExtractFiberSubset(PlanarFigure *pf); + std::vector ExtractFiberIdSubset(PlanarFigure* pf); vtkSmartPointer GeneratePolyDataByIds( std::vector ); // get/set data void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData(); QStringList GetAvailableColorCodings(); char* GetCurrentColorCoding(); - itkGetMacro(NumFibers, int); + itkGetMacro(NumFibers, int) // copy fiber bundle mitk::FiberBundleX::Pointer GetDeepCopy(); + bool Equals(FiberBundleX* fib); void GenerateFiberIds(); protected: FiberBundleX( vtkPolyData* fiberPolyData = NULL ); virtual ~FiberBundleX(); itk::Point GetItkPoint(double point[3]); // calculate geometry from fiber extent void UpdateFiberGeometry(); // calculate colorcoding values according to m_CurrentColorCoding void UpdateColorCoding(); private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains fiber ids vtkSmartPointer m_FiberIdDataSet; char* m_CurrentColorCoding; int m_NumFibers; }; } // namespace mitk #endif /* _MITK_FiberBundleX_H */ diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXReader.h b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXReader.h index bee02c243d..618226c71b 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXReader.h +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXReader.h @@ -1,76 +1,77 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkFiberBundleXReader_h #define __mitkFiberBundleXReader_h #include #include #include #include +#include namespace mitk { /** \brief */ - class FiberBundleXReader : public FileReader, public BaseProcess + class MitkDiffusionImaging_EXPORT FiberBundleXReader : public FileReader, public BaseProcess { public: /** Types for the standardized TractContainer **/ /* direct linked includes of mitkFiberBundleX DataStructure */ typedef mitk::FiberBundleX OutputType; mitkClassMacro( FiberBundleXReader, BaseProcess ); itkNewMacro(Self); const char* GetFileName() const; void SetFileName(const char* aFileName); const char* GetFilePrefix() const; void SetFilePrefix(const char* aFilePrefix); const char* GetFilePattern() const; void SetFilePattern(const char* aFilePattern); static bool CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern); // itkGetMacro(GroupFiberBundleX, FiberGroupType::Pointer); // itkGetMacro(TractContainer, ContainerType::Pointer); virtual void Update(); protected: /** Does the real work. */ virtual void GenerateData(); virtual void GenerateOutputInformation(); OutputType::Pointer m_OutputCache; std::string m_FileName; std::string m_FilePrefix; std::string m_FilePattern; private: void operator=(const Self&); //purposely not implemented }; } //namespace MITK #endif // __mitkFiberBundleXReader_h diff --git a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp index 5292efe764..ab44784827 100644 --- a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp +++ b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp @@ -1,119 +1,134 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /* * mitkPlanarFigureComposite.cpp * mitk-all * * Created by HAL9000 on 2/4/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkPlanarFigureComposite.h" mitk::PlanarFigureComposite::PlanarFigureComposite() { m_PFVector = CompositionContainer::New(); m_DNVector = DataNodeContainer::New(); } mitk::PlanarFigureComposite::~PlanarFigureComposite() { } void mitk::PlanarFigureComposite::addDataNode(mitk::DataNode::Pointer dnode) { m_DNVector->InsertElement(m_DNVector->Size(), dnode); } void mitk::PlanarFigureComposite::addPlanarFigure(PlanarFigure::Pointer pf) { m_PFVector->InsertElement(m_PFVector->Size(), pf); } void mitk::PlanarFigureComposite::replaceDataNodeAt(int idx, mitk::DataNode::Pointer dn) { m_DNVector->SetElement( idx, dn ); } void mitk::PlanarFigureComposite::setOperationType(PFCompositionOperation pfcOp) { this->m_compOperation = pfcOp; } mitk::PFCompositionOperation mitk::PlanarFigureComposite::getOperationType() { return this->m_compOperation; } void mitk::PlanarFigureComposite::setDisplayName(std::string displName) { m_name = displName; } std::string mitk::PlanarFigureComposite::getDisplayName() { return m_name; } int mitk::PlanarFigureComposite::getNumberOfChildren() { return m_PFVector->Size(); } mitk::PlanarFigure::Pointer mitk::PlanarFigureComposite::getChildAt(int idx) { return m_PFVector->ElementAt(idx); } mitk::DataNode::Pointer mitk::PlanarFigureComposite::getDataNodeAt(int idx) { return m_DNVector->ElementAt(idx); } //musthave implementations from superclass.... not sure if return true makes sense bool mitk::PlanarFigureComposite::SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist ) { return true; } void mitk::PlanarFigureComposite::GeneratePolyLine() { } void mitk::PlanarFigureComposite::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/) { // A circle does not require a helper object } void mitk::PlanarFigureComposite::EvaluateFeaturesInternal() { } void mitk::PlanarFigureComposite::PrintSelf( std::ostream& os, itk::Indent indent) const { } diff --git a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h index 09212e2065..f7e8bc46f0 100644 --- a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h +++ b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h @@ -1,110 +1,125 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /* * mitkPlanarFigureComposite.h * mitk-all * * Created by HAL9000 on 2/4/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #ifndef _MITK_PLANARFIGURECOMPOSITE_H #define _MITK_PLANARFIGURECOMPOSITE_H #include "mitkCommon.h" #include "mitkBaseData.h" #include "MitkDiffusionImagingExports.h" #include "mitkPlanarFigure.h" #include "itkVectorContainer.h" #include "mitkDataNode.h" namespace mitk { enum PFCompositionOperation { PFCOMPOSITION_AND_OPERATION, PFCOMPOSITION_OR_OPERATION, PFCOMPOSITION_NOT_OPERATION, }; class MitkDiffusionImaging_EXPORT PlanarFigureComposite : public PlanarFigure { typedef itk::VectorContainer CompositionContainer; typedef itk::VectorContainer DataNodeContainer; public: mitkClassMacro(PlanarFigureComposite, PlanarFigure); itkNewMacro( Self ); // ///MUST HAVE IMPLEMENTATION////// bool SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist ); unsigned int GetMinimumNumberOfControlPoints() const { return 0; } /** \brief Circle has 2 control points per definition. */ unsigned int GetMaximumNumberOfControlPoints() const { return 0; } // ///////////////////////// int getNumberOfChildren(); mitk::PlanarFigure::Pointer getChildAt(int); void addPlanarFigure(PlanarFigure::Pointer); mitk::DataNode::Pointer getDataNodeAt(int); void addDataNode(mitk::DataNode::Pointer); void replaceDataNodeAt(int, mitk::DataNode::Pointer); // set if this compsition is AND, OR, NOT void setOperationType(PFCompositionOperation); PFCompositionOperation getOperationType(); void setDisplayName(std::string); std::string getDisplayName(); protected: PlanarFigureComposite(); virtual ~PlanarFigureComposite(); // ///MUST HAVE IMPLEMENTATION////// /** \brief Generates the poly-line representation of the planar figure. */ virtual void GeneratePolyLine(); /** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/ virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight); /** \brief Calculates feature quantities of the planar figure. */ virtual void EvaluateFeaturesInternal(); virtual void PrintSelf( std::ostream &os, itk::Indent indent ) const; // //////////////////// private: //this vector takes planarfigures and planarfigureComosite types CompositionContainer::Pointer m_PFVector; PFCompositionOperation m_compOperation; DataNodeContainer::Pointer m_DNVector; std::string m_name; }; } #endif diff --git a/Modules/DiffusionImaging/IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp b/Modules/DiffusionImaging/IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp index 89a57a2c77..2b926f69b2 100644 --- a/Modules/DiffusionImaging/IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp +++ b/Modules/DiffusionImaging/IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp @@ -1,409 +1,413 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkNrrdTbssImageReader_cpp #define __mitkNrrdTbssImageReader_cpp #include "mitkNrrdTbssImageReader.h" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkNiftiImageIO.h" #include #include #include #include "itksys/SystemTools.hxx" namespace mitk { void NrrdTbssImageReader ::GenerateData() { // Since everything is completely read in GenerateOutputInformation() it is stored // in a cache variable. A timestamp is associated. // If the timestamp of the cache variable is newer than the MTime, we only need to // assign the cache variable to the DataObject. // Otherwise, the tree must be read again from the file and OuputInformation must // be updated! if ( ( ! m_OutputCache ) || ( this->GetMTime( ) > m_CacheTime.GetMTime( ) ) ) { this->GenerateOutputInformation(); itkWarningMacro("Cache regenerated!"); } if (!m_OutputCache) { itkWarningMacro("Tree cache is empty!") } int vecsize = m_OutputCache->GetImage()->GetVectorLength(); static_cast(this->GetOutput()) ->SetImage(m_OutputCache->GetImage()); static_cast(this->GetOutput()) ->SetGroupInfo(m_OutputCache->GetGroupInfo()); static_cast(this->GetOutput()) ->SetMetaInfo(m_OutputCache->GetMetaInfo()); static_cast(this->GetOutput()) ->SetIsMeta(m_OutputCache->GetIsMeta()); static_cast(this->GetOutput()) ->SetContainsDistanceMap(m_OutputCache->GetContainsDistanceMap()); static_cast(this->GetOutput()) ->SetContainsMeanSkeleton(m_OutputCache->GetContainsMeanSkeleton()); static_cast(this->GetOutput()) ->SetContainsSkeletonMask(m_OutputCache->GetContainsSkeletonMask()); static_cast(this->GetOutput()) ->SetContainsGradient(m_OutputCache->GetContainsGradient()); static_cast(this->GetOutput()) ->InitializeFromVectorImage(); } void NrrdTbssImageReader ::GenerateOutputInformation() { OutputType::Pointer outputForCache = OutputType::New(); if ( m_FileName == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { MITK_INFO << " ** Changing locale from " << setlocale(LC_ALL, NULL) << " to '" << locale << "'"; setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } MITK_INFO << "NrrdTbssImageReader READING IMAGE INFORMATION"; ImageType::Pointer img; std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName); ext = itksys::SystemTools::LowerCase(ext); if (ext == ".tbss") { typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(this->m_FileName); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); reader->SetImageIO(io); reader->Update(); img = reader->GetOutput(); MITK_INFO << "NrrdTbssImageReader READING HEADER INFORMATION"; itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; //int numberOfGradientImages = 0; std::string measurementInfo; bool isMeta = false; bool containsSkeleton; bool containsSkeletonMask; bool containsGradient; bool containsDistanceMap; std::vector > metaInfo; std::vector< std::pair > groups; for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); MITK_INFO << *itKey << " ---> " << metaString; if (itKey->find("Group_index") != std::string::npos) { std::vector tokens; this->Tokenize(metaString, tokens, " "); - if(tokens.size()==2) - { - std::cout << tokens.at(0) << " " << tokens.at(1) << std::endl; + std::pair< std::string, int > p; - std::pair< std::string, int > p; - p.first = tokens.at(0); - std::string s = tokens.at(1); - p.second = atoi(tokens.at(1).c_str()); - groups.push_back(p); + p.first=""; + for (int i=0; ifind("Measurement info") != std::string::npos) { measurementInfo = metaString; } else if(itKey->find("meta") != std::string::npos) { if(metaString == "true") { isMeta = true; } } else if(itKey->find("mean fa skeleton mask") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::MEAN_FA_SKELETON_MASK; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsSkeletonMask = true; } else if(itKey->find("mean fa skeleton") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::MEAN_FA_SKELETON; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsSkeleton = true; } else if(itKey->find("gradient_x") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::GRADIENT_X; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsGradient = true; } else if(itKey->find("gradient_y") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::GRADIENT_Y; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsGradient = true; } else if(itKey->find("gradient_z") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::GRADIENT_Z; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsGradient = true; } else if(itKey->find("tubular structure") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::TUBULAR_STRUCTURE; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); } else if(itKey->find("distance map") != std::string::npos) { std::pair p; p.first = mitk::TbssImage::DISTANCE_MAP; p.second = atoi(metaString.c_str()); metaInfo.push_back(p); containsDistanceMap = true; } } outputForCache->SetIsMeta(isMeta); outputForCache->SetContainsGradient(containsGradient); outputForCache->SetContainsSkeletonMask(containsSkeletonMask); outputForCache->SetContainsMeanSkeleton(containsSkeleton); outputForCache->SetContainsDistanceMap(containsDistanceMap); outputForCache->SetGroupInfo(groups); outputForCache->SetMeasurementInfo(measurementInfo); outputForCache->SetMetaInfo(metaInfo); } // This call updates the output information of the associated VesselTreeData outputForCache->SetImage(img); // outputForCache->SetB_Value(m_B_Value); //outputForCache->SetDirections(m_DiffusionVectors); // outputForCache->SetOriginalDirections(m_OriginalDiffusionVectors); // outputForCache->SetMeasurementFrame(m_MeasurementFrame); // Since we have already read the tree, we can store it in a cache variable // so that it can be assigned to the DataObject in GenerateData(); m_OutputCache = outputForCache; m_CacheTime.Modified(); try { MITK_INFO << " ** Changing locale back from " << setlocale(LC_ALL, NULL) << " to '" << currLocale << "'"; setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } } const char* NrrdTbssImageReader ::GetFileName() const { return m_FileName.c_str(); } void NrrdTbssImageReader ::SetFileName(const char* aFileName) { m_FileName = aFileName; } const char* NrrdTbssImageReader ::GetFilePrefix() const { return m_FilePrefix.c_str(); } void NrrdTbssImageReader ::SetFilePrefix(const char* aFilePrefix) { m_FilePrefix = aFilePrefix; } const char* NrrdTbssImageReader ::GetFilePattern() const { return m_FilePattern.c_str(); } void NrrdTbssImageReader ::SetFilePattern(const char* aFilePattern) { m_FilePattern = aFilePattern; } bool NrrdTbssImageReader ::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern) { // First check the extension if( filename == "" ) return false; // check if image is serie if( filePattern != "" && filePrefix != "" ) return false; std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); ext = itksys::SystemTools::LowerCase(ext); if (ext == ".tbss") { itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(filename); try { reader->Update(); } catch(itk::ExceptionObject e) { MITK_INFO << e.GetDescription(); return false; } /* typename ImageType::Pointer img = reader->GetOutput(); itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("tbss") != std::string::npos) { if (metaString.find("ROI") != std::string::npos) { return true; } } } } */ // return false; return true; } return false; } } //namespace MITK #endif diff --git a/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp b/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp index 5e1ba61ac8..86c834df94 100644 --- a/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp +++ b/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp @@ -1,885 +1,791 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp #define __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -#if BOOST_VERSION / 100000 > 0 -#if BOOST_VERSION / 100 % 1000 > 34 -#include -#endif -#endif +#include #include "itkPointShell.h" +using namespace boost::math; + namespace itk { #define QBALL_ANAL_RECON_PI M_PI - template< class T, class TG, class TO, int L, int NODF> - AnalyticalDiffusionQballReconstructionImageFilter - ::AnalyticalDiffusionQballReconstructionImageFilter() : +template< class T, class TG, class TO, int L, int NODF> +AnalyticalDiffusionQballReconstructionImageFilter +::AnalyticalDiffusionQballReconstructionImageFilter() : m_GradientDirectionContainer(NULL), m_NumberOfGradientDirections(0), m_NumberOfBaselineImages(1), m_Threshold(NumericTraits< ReferencePixelType >::NonpositiveMin()), m_BValue(1.0), m_Lambda(0.0), m_DirectionsDuplicated(false), m_Delta1(0.001), m_Delta2(0.001) - { +{ // At least 1 inputs is necessary for a vector image. // For images added one at a time we need at least six this->SetNumberOfRequiredInputs( 1 ); - } - - - template< - class TReferenceImagePixelType, - class TGradientImagePixelType, - class TOdfPixelType, - int NOrderL, - int NrOdfDirections> - typename itk::AnalyticalDiffusionQballReconstructionImageFilter< - TReferenceImagePixelType,TGradientImagePixelType,TOdfPixelType, - NOrderL,NrOdfDirections>::OdfPixelType - itk::AnalyticalDiffusionQballReconstructionImageFilter - - ::Normalize( OdfPixelType odf, - typename NumericTraits::AccumulateType b0 ) - { - switch( m_NormalizationMethod ) - { - case QBAR_STANDARD: - { - TOdfPixelType sum = 0; +} + + +template< + class TReferenceImagePixelType, + class TGradientImagePixelType, + class TOdfPixelType, + int NOrderL, + int NrOdfDirections> +typename itk::AnalyticalDiffusionQballReconstructionImageFilter< +TReferenceImagePixelType,TGradientImagePixelType,TOdfPixelType, +NOrderL,NrOdfDirections>::OdfPixelType +itk::AnalyticalDiffusionQballReconstructionImageFilter + +::Normalize( OdfPixelType odf, + typename NumericTraits::AccumulateType b0 ) +{ + switch( m_NormalizationMethod ) + { + case QBAR_STANDARD: + { + TOdfPixelType sum = 0; - for(int i=0; i0) + } + if(sum>0) odf /= sum; - return odf; - break; - } - case QBAR_B_ZERO_B_VALUE: + return odf; + break; + } + case QBAR_B_ZERO_B_VALUE: + { + for(int i=0; i - vnl_vector - itk::AnalyticalDiffusionQballReconstructionImageFilter - - ::PreNormalize( vnl_vector vec, - typename NumericTraits::AccumulateType b0 ) - { - switch( m_NormalizationMethod ) +vnl_vector +itk::AnalyticalDiffusionQballReconstructionImageFilter + +::PreNormalize( vnl_vector vec, + typename NumericTraits::AccumulateType b0 ) +{ + switch( m_NormalizationMethod ) + { + case QBAR_STANDARD: + { + return vec; + break; + } + case QBAR_B_ZERO_B_VALUE: + { + int n = vec.size(); + for(int i=0; i=1) + else if (vec[i]>=1) vec[i] = 1-m_Delta2/2; - else if (vec[i]>=1-m_Delta2) + else if (vec[i]>=1-m_Delta2) vec[i] = 1-m_Delta2/2-(1-vec[i])*(1-vec[i])/(2*m_Delta2); - vec[i] = log(-log(vec[i])); - } - return vec; - break; - } + vec[i] = log(-log(vec[i])); } - return vec; - } - - template< class T, class TG, class TO, int L, int NODF> - void AnalyticalDiffusionQballReconstructionImageFilter - ::BeforeThreadedGenerateData() - { - // If we have more than 2 inputs, then each input, except the first is a - // gradient image. The number of gradient images must match the number of - // gradient directions. - //const unsigned int numberOfInputs = this->GetNumberOfInputs(); - - // There need to be at least 6 gradient directions to be able to compute the - // tensor basis - if( m_NumberOfGradientDirections < 6 ) - { - itkExceptionMacro( << "At least 6 gradient directions are required" ); - } + break; + } + } - // Input must be an itk::VectorImage. - std::string gradientImageClassName( - this->ProcessObject::GetInput(0)->GetNameOfClass()); - if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 ) - { - itkExceptionMacro( << - "There is only one Gradient image. I expect that to be a VectorImage. " - << "But its of type: " << gradientImageClassName ); - } + return vec; +} - this->ComputeReconstructionMatrix(); - - typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >( - this->ProcessObject::GetInput(0) ); - - m_BZeroImage = BZeroImageType::New(); - m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing - m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin - m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction - m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); - m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); - m_BZeroImage->Allocate(); - - m_ODFSumImage = BZeroImageType::New(); - m_ODFSumImage->SetSpacing( img->GetSpacing() ); // Set the image spacing - m_ODFSumImage->SetOrigin( img->GetOrigin() ); // Set the image origin - m_ODFSumImage->SetDirection( img->GetDirection() ); // Set the image direction - m_ODFSumImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); - m_ODFSumImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); - m_ODFSumImage->Allocate(); - - m_CoefficientImage = CoefficientImageType::New(); - m_CoefficientImage->SetSpacing( img->GetSpacing() ); // Set the image spacing - m_CoefficientImage->SetOrigin( img->GetOrigin() ); // Set the image origin - m_CoefficientImage->SetDirection( img->GetDirection() ); // Set the image direction - m_CoefficientImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); - m_CoefficientImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); - m_CoefficientImage->Allocate(); - - if(m_NormalizationMethod == QBAR_SOLID_ANGLE || - m_NormalizationMethod == QBAR_NONNEG_SOLID_ANGLE) - { - m_Lambda = 0.0; - } +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::BeforeThreadedGenerateData() +{ + // If we have more than 2 inputs, then each input, except the first is a + // gradient image. The number of gradient images must match the number of + // gradient directions. + //const unsigned int numberOfInputs = this->GetNumberOfInputs(); + + // There need to be at least 6 gradient directions to be able to compute the + // tensor basis + if( m_NumberOfGradientDirections < 6 ) + { + itkExceptionMacro( << "At least 6 gradient directions are required" ); + } - } + // Input must be an itk::VectorImage. + std::string gradientImageClassName( + this->ProcessObject::GetInput(0)->GetNameOfClass()); + if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 ) + { + itkExceptionMacro( << + "There is only one Gradient image. I expect that to be a VectorImage. " + << "But its of type: " << gradientImageClassName ); + } - template< class T, class TG, class TO, int L, int NODF> - void AnalyticalDiffusionQballReconstructionImageFilter - ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, - int ) - { - typename OutputImageType::Pointer outputImage = - static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); + this->ComputeReconstructionMatrix(); + + typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >( + this->ProcessObject::GetInput(0) ); + + m_BZeroImage = BZeroImageType::New(); + m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing + m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin + m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction + m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); + m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); + m_BZeroImage->Allocate(); + + m_ODFSumImage = BZeroImageType::New(); + m_ODFSumImage->SetSpacing( img->GetSpacing() ); // Set the image spacing + m_ODFSumImage->SetOrigin( img->GetOrigin() ); // Set the image origin + m_ODFSumImage->SetDirection( img->GetDirection() ); // Set the image direction + m_ODFSumImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); + m_ODFSumImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); + m_ODFSumImage->Allocate(); + + m_CoefficientImage = CoefficientImageType::New(); + m_CoefficientImage->SetSpacing( img->GetSpacing() ); // Set the image spacing + m_CoefficientImage->SetOrigin( img->GetOrigin() ); // Set the image origin + m_CoefficientImage->SetDirection( img->GetDirection() ); // Set the image direction + m_CoefficientImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); + m_CoefficientImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); + m_CoefficientImage->Allocate(); + + if(m_NormalizationMethod == QBAR_SOLID_ANGLE || m_NormalizationMethod == QBAR_NONNEG_SOLID_ANGLE) + m_Lambda = 0.0; +} - ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); - oit.GoToBegin(); +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + int ) +{ + typename OutputImageType::Pointer outputImage = + static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); - ImageRegionIterator< BZeroImageType > oit2(m_BZeroImage, outputRegionForThread); - oit2.GoToBegin(); + ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); + oit.GoToBegin(); - ImageRegionIterator< FloatImageType > oit3(m_ODFSumImage, outputRegionForThread); - oit3.GoToBegin(); + ImageRegionIterator< BZeroImageType > oit2(m_BZeroImage, outputRegionForThread); + oit2.GoToBegin(); - ImageRegionIterator< CoefficientImageType > oit4(m_CoefficientImage, outputRegionForThread); - oit4.GoToBegin(); + ImageRegionIterator< FloatImageType > oit3(m_ODFSumImage, outputRegionForThread); + oit3.GoToBegin(); - typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType; - typedef typename GradientImagesType::PixelType GradientVectorType; - typename GradientImagesType::Pointer gradientImagePointer = NULL; + ImageRegionIterator< CoefficientImageType > oit4(m_CoefficientImage, outputRegionForThread); + oit4.GoToBegin(); - // Would have liked a dynamic_cast here, but seems SGI doesn't like it - // The enum will ensure that an inappropriate cast is not done - gradientImagePointer = static_cast< GradientImagesType * >( - this->ProcessObject::GetInput(0) ); + typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType; + typedef typename GradientImagesType::PixelType GradientVectorType; + typename GradientImagesType::Pointer gradientImagePointer = NULL; - GradientIteratorType git(gradientImagePointer, outputRegionForThread ); - git.GoToBegin(); + // Would have liked a dynamic_cast here, but seems SGI doesn't like it + // The enum will ensure that an inappropriate cast is not done + gradientImagePointer = static_cast< GradientImagesType * >( + this->ProcessObject::GetInput(0) ); - // Compute the indicies of the baseline images and gradient images - std::vector baselineind; // contains the indicies of - // the baseline images - std::vector gradientind; // contains the indicies of - // the gradient images + GradientIteratorType git(gradientImagePointer, outputRegionForThread ); + git.GoToBegin(); - for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); - gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) - { - if(gdcit.Value().one_norm() <= 0.0) - { + // Compute the indicies of the baseline images and gradient images + std::vector baselineind; // contains the indicies of + // the baseline images + std::vector gradientind; // contains the indicies of + // the gradient images + + for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); + gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) + { + if(gdcit.Value().one_norm() <= 0.0) baselineind.push_back(gdcit.Index()); - } - else - { + else gradientind.push_back(gdcit.Index()); - } - } + } - if( m_DirectionsDuplicated ) - { - int gradIndSize = gradientind.size(); - for(int i=0; i::AccumulateType b0 = NumericTraits::Zero; + typename NumericTraits::AccumulateType b0 = NumericTraits::Zero; - // Average the baseline image pixels - for(unsigned int i = 0; i < baselineind.size(); ++i) - { + // Average the baseline image pixels + for(unsigned int i = 0; i < baselineind.size(); ++i) + { b0 += b[baselineind[i]]; - } - b0 /= this->m_NumberOfBaselineImages; + } + b0 /= this->m_NumberOfBaselineImages; - OdfPixelType odf(0.0); - typename CoefficientImageType::PixelType coeffPixel(0.0); - vnl_vector B(m_NumberOfGradientDirections); + OdfPixelType odf(0.0); + typename CoefficientImageType::PixelType coeffPixel(0.0); + vnl_vector B(m_NumberOfGradientDirections); - if( (b0 != 0) && (b0 >= m_Threshold) ) - { + if( (b0 != 0) && (b0 >= m_Threshold) ) + { for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ ) { - B[i] = static_cast(b[gradientind[i]]); + B[i] = static_cast(b[gradientind[i]]); } B = PreNormalize(B, b0); if(m_NormalizationMethod == QBAR_SOLID_ANGLE) { - vnl_vector coeffs(m_NumberCoefficients); - coeffs = ( (*m_CoeffReconstructionMatrix) * B ); - coeffs[0] += 1.0/(2.0*sqrt(QBALL_ANAL_RECON_PI)); - odf = ( (*m_SphericalHarmonicBasisMatrix) * coeffs ).data_block(); - coeffPixel = coeffs.data_block(); + vnl_vector coeffs(m_NumberCoefficients); + coeffs = ( (*m_CoeffReconstructionMatrix) * B ); + coeffs[0] += 1.0/(2.0*sqrt(QBALL_ANAL_RECON_PI)); + odf = ( (*m_SphericalHarmonicBasisMatrix) * coeffs ).data_block(); + coeffPixel = coeffs.data_block(); } else if(m_NormalizationMethod == QBAR_NONNEG_SOLID_ANGLE) { - /** this would be the place to implement a non-negative + /** this would be the place to implement a non-negative * solver for quadratic programming problem: * min .5*|| Bc-s ||^2 subject to -CLPc <= 4*pi*ones * (refer to MICCAI 2009 Goh et al. "Estimating ODFs with PDF constraints") * .5*|| Bc-s ||^2 == .5*c'B'Bc - x'B's + .5*s's */ - itkExceptionMacro( << "Nonnegative Solid Angle not yet implemented"); - + itkExceptionMacro( << "Nonnegative Solid Angle not yet implemented"); } else { - odf = ( (*m_ReconstructionMatrix) * B ).data_block(); + odf = ( (*m_ReconstructionMatrix) * B ).data_block(); } odf = Normalize(odf, b0); - } + } - oit.Set( odf ); - oit2.Set( b0 ); - float sum = 0; - for (int k=0; k - void AnalyticalDiffusionQballReconstructionImageFilter - ::tofile2(vnl_matrix *pA, std::string fname) - { - vnl_matrix A = (*pA); - ofstream myfile; - std::locale C("C"); - std::locale originalLocale = myfile.getloc(); - myfile.imbue(C); - - myfile.open (fname.c_str()); - myfile << "A1=["; - for(int i=0; i +void AnalyticalDiffusionQballReconstructionImageFilter +::tofile2(vnl_matrix *pA, std::string fname) +{ + vnl_matrix A = (*pA); + ofstream myfile; + std::locale C("C"); + std::locale originalLocale = myfile.getloc(); + myfile.imbue(C); + + myfile.open (fname.c_str()); + myfile << "A1=["; + for(int i=0; i - double AnalyticalDiffusionQballReconstructionImageFilter - ::factorial(int number) { - if(number <= 1) return 1; - double result = 1.0; - for(int i=1; i<=number; i++) - result *= i; - return result; - } - - template< class T, class TG, class TO, int L, int NODF> - void AnalyticalDiffusionQballReconstructionImageFilter - ::Cart2Sph(double x, double y, double z, double *cart) - { - double phi, th, rad; - rad = sqrt(x*x+y*y+z*z); - th = atan2(z,sqrt(x*x+y*y)); - phi = atan2(y,x); - th = -th+QBALL_ANAL_RECON_PI/2; - phi = -phi+QBALL_ANAL_RECON_PI; - cart[0] = phi; - cart[1] = th; - cart[2] = rad; - } - - template< class T, class TG, class TO, int L, int NODF> - double AnalyticalDiffusionQballReconstructionImageFilter - ::legendre0(int l) - { - if( l%2 != 0 ) - { - return 0; - } - else - { - double prod1 = 1.0; - for(int i=1;i - double AnalyticalDiffusionQballReconstructionImageFilter - ::spherical_harmonic(int m,int l,double theta,double phi, bool complexPart) - { - if( theta < 0 || theta > QBALL_ANAL_RECON_PI ) - { - std::cout << "bad range" << std::endl; - return 0; - } - - if( phi < 0 || phi > 2*QBALL_ANAL_RECON_PI ) - { - std::cout << "bad range" << std::endl; - return 0; + myfile << ";"; } + } + myfile << "];"; + myfile.close(); - double pml = 0; - double fac1 = factorial(l+m); - double fac2 = factorial(l-m); - - if( m<0 ) - { -#if BOOST_VERSION / 100000 > 0 -#if BOOST_VERSION / 100 % 1000 > 34 - pml = ::boost::math::legendre_p(l, -m, cos(theta)); -#else - std::cout << "ERROR: Boost 1.35 minimum required" << std::endl; -#endif -#else - std::cout << "ERROR: Boost 1.35 minimum required" << std::endl; -#endif - double mypow = pow(-1.0,-m); - double myfac = (fac1/fac2); - pml *= mypow*myfac; - } - else - { -#if BOOST_VERSION / 100000 > 0 -#if BOOST_VERSION / 100 % 1000 > 34 - pml = ::boost::math::legendre_p(l, m, cos(theta)); -#endif -#endif - } + myfile.imbue( originalLocale ); +} - //std::cout << "legendre(" << l << "," << m << "," << cos(theta) << ") = " << pml << std::endl; +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::Cart2Sph(double x, double y, double z, double *spherical) +{ + double phi, theta, r; + r = sqrt(x*x+y*y+z*z); - double retval = sqrt(((2.0*(double)l+1.0)/(4.0*QBALL_ANAL_RECON_PI))*(fac2/fac1)) * pml; - if( !complexPart ) - { - retval *= cos(m*phi); - } - else - { - retval *= sin(m*phi); - } - //std::cout << retval << std::endl; - return retval; - } - - template< class T, class TG, class TO, int L, int NODF> - double AnalyticalDiffusionQballReconstructionImageFilter - ::Yj(int m, int k, double theta, double phi) - { - if( -k <= m && m < 0 ) - { - return sqrt(2.0) * spherical_harmonic(m,k,theta,phi,false); - } - - if( m == 0 ) - return spherical_harmonic(0,k,theta,phi,false); + if( r +double AnalyticalDiffusionQballReconstructionImageFilter +::Yj(int m, int l, double theta, double phi) +{ + if (m<0) + return sqrt(2.0)*spherical_harmonic_r(l, -m, theta, phi); + else if (m==0) + return spherical_harmonic_r(l, m, theta, phi); + else + return pow(-1.0,m)*sqrt(2.0)*spherical_harmonic_i(l, m, theta, phi); + + return 0; +} +template< class T, class TG, class TO, int L, int NODF> +double AnalyticalDiffusionQballReconstructionImageFilter +::Legendre0(int l) +{ + if( l%2 != 0 ) + { return 0; - } - - + } + else + { + double prod1 = 1.0; + for(int i=1;i - void AnalyticalDiffusionQballReconstructionImageFilter - ::ComputeReconstructionMatrix() - { +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::ComputeReconstructionMatrix() +{ - //for(int i=-6;i<7;i++) - // std::cout << boost::math::legendre_p(6, i, 0.65657) << std::endl; + //for(int i=-6;i<7;i++) + // std::cout << boost::math::legendre_p(6, i, 0.65657) << std::endl; - if( m_NumberOfGradientDirections < 6 ) - { - itkExceptionMacro( << "Not enough gradient directions supplied. Need to supply at least 6" ); - } + if( m_NumberOfGradientDirections < 6 ) + { + itkExceptionMacro( << "Not enough gradient directions supplied. Need to supply at least 6" ); + } - { - // check for duplicate diffusion gradients - bool warning = false; - for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin(); + { + // check for duplicate diffusion gradients + bool warning = false; + for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin(); gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1) - { + { for(GradientDirectionContainerType::ConstIterator gdcit2 = this->m_GradientDirectionContainer->Begin(); - gdcit2 != this->m_GradientDirectionContainer->End(); ++gdcit2) + gdcit2 != this->m_GradientDirectionContainer->End(); ++gdcit2) { - if(gdcit1.Value() == gdcit2.Value() && gdcit1.Index() != gdcit2.Index()) - { - itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." ); - warning = true; - break; - } + if(gdcit1.Value() == gdcit2.Value() && gdcit1.Index() != gdcit2.Index()) + { + itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." ); + warning = true; + break; + } } if (warning) break; - } - - // handle acquisition schemes where only half of the spherical - // shell is sampled by the gradient directions. In this case, - // each gradient direction is duplicated in negative direction. - vnl_vector centerMass(3); - centerMass.fill(0.0); - int count = 0; - for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin(); + } + + // handle acquisition schemes where only half of the spherical + // shell is sampled by the gradient directions. In this case, + // each gradient direction is duplicated in negative direction. + vnl_vector centerMass(3); + centerMass.fill(0.0); + int count = 0; + for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin(); gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1) - { + { if(gdcit1.Value().one_norm() > 0.0) { - centerMass += gdcit1.Value(); - count ++; + centerMass += gdcit1.Value(); + count ++; } - } - centerMass /= count; - if(centerMass.two_norm() > 0.1) - { + } + centerMass /= count; + if(centerMass.two_norm() > 0.1) + { m_DirectionsDuplicated = true; m_NumberOfGradientDirections *= 2; - } } + } - vnl_matrix *Q - = new vnl_matrix(3, m_NumberOfGradientDirections); + vnl_matrix *Q = new vnl_matrix(3, m_NumberOfGradientDirections); - { - int i = 0; - for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); + { + int i = 0; + for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) - { + { if(gdcit.Value().one_norm() > 0.0) { - double x = gdcit.Value().get(0); - double y = gdcit.Value().get(1); - double z = gdcit.Value().get(2); - double cart[3]; - Cart2Sph(x,y,z,cart); - (*Q)(0,i) = cart[0]; - (*Q)(1,i) = cart[1]; - (*Q)(2,i++) = cart[2]; - } - } - if(m_DirectionsDuplicated) - { - for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); - gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) - { - if(gdcit.Value().one_norm() > 0.0) - { double x = gdcit.Value().get(0); double y = gdcit.Value().get(1); double z = gdcit.Value().get(2); double cart[3]; Cart2Sph(x,y,z,cart); (*Q)(0,i) = cart[0]; (*Q)(1,i) = cart[1]; (*Q)(2,i++) = cart[2]; - } } - } } + if(m_DirectionsDuplicated) + { + for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); + gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) + { + if(gdcit.Value().one_norm() > 0.0) + { + double x = gdcit.Value().get(0); + double y = gdcit.Value().get(1); + double z = gdcit.Value().get(2); + double cart[3]; + Cart2Sph(x,y,z,cart); + (*Q)(0,i) = cart[0]; + (*Q)(1,i) = cart[1]; + (*Q)(2,i++) = cart[2]; + } + } + } + } - int l = L; - m_NumberCoefficients = (int)(l*l + l + 2.0)/2.0 + l; - vnl_matrix* B = new vnl_matrix(m_NumberOfGradientDirections,m_NumberCoefficients); - vnl_matrix* _L = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); - _L->fill(0.0); - vnl_matrix* LL = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); - LL->fill(0.0); - vnl_matrix* P = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); - P->fill(0.0); - vnl_matrix* Inv = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); - P->fill(0.0); - vnl_vector* lj = new vnl_vector(m_NumberCoefficients); - m_LP = new vnl_vector(m_NumberCoefficients); - - for(unsigned int i=0; i* B = new vnl_matrix(m_NumberOfGradientDirections,m_NumberCoefficients); + vnl_matrix* _L = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); + _L->fill(0.0); + vnl_matrix* LL = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); + LL->fill(0.0); + vnl_matrix* P = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); + P->fill(0.0); + vnl_matrix* Inv = new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients); + P->fill(0.0); + vnl_vector* lj = new vnl_vector(m_NumberCoefficients); + m_LP = new vnl_vector(m_NumberCoefficients); + + for(unsigned int i=0; i temp((*_L)*(*_L)); + LL->update(*_L); + *LL *= *_L; + //tofile2(LL,"LL"); - for(int i=0; i(B->transpose()); - //tofile2(&m_B_t,"m_B_t"); - vnl_matrix B_t_B = (*m_B_t) * (*B); - //tofile2(&B_t_B,"B_t_B"); - vnl_matrix lambdaLL(m_NumberCoefficients,m_NumberCoefficients); - lambdaLL.update((*LL)); - lambdaLL *= m_Lambda; - //tofile2(&lambdaLL,"lLL"); - - vnl_matrix tmp( B_t_B + lambdaLL); - vnl_matrix_inverse *pseudoInverse - = new vnl_matrix_inverse( tmp ); - - (*Inv) = pseudoInverse->pinverse(); - //tofile2(Inv,"Inv"); - vnl_matrix temp((*Inv) * (*m_B_t)); - double fac1 = (1.0/(16.0*QBALL_ANAL_RECON_PI*QBALL_ANAL_RECON_PI)); - switch(m_NormalizationMethod) + else { - case QBAR_ADC_ONLY: - case QBAR_RAW_SIGNAL: - break; - case QBAR_STANDARD: - case QBAR_B_ZERO_B_VALUE: - case QBAR_B_ZERO: - case QBAR_NONE: - temp = (*P) * temp; - break; - case QBAR_SOLID_ANGLE: - temp = fac1 * (*P) * (*_L) * temp; - break; - case QBAR_NONNEG_SOLID_ANGLE: - break; + (*P)(i,i) = Legendre0((*lj)[i]); } + } + m_B_t = new vnl_matrix(B->transpose()); + //tofile2(&m_B_t,"m_B_t"); + vnl_matrix B_t_B = (*m_B_t) * (*B); + //tofile2(&B_t_B,"B_t_B"); + vnl_matrix lambdaLL(m_NumberCoefficients,m_NumberCoefficients); + lambdaLL.update((*LL)); + lambdaLL *= m_Lambda; + //tofile2(&lambdaLL,"lLL"); + + vnl_matrix tmp( B_t_B + lambdaLL); + vnl_matrix_inverse *pseudoInverse + = new vnl_matrix_inverse( tmp ); + + (*Inv) = pseudoInverse->pinverse(); + //tofile2(Inv,"Inv"); + vnl_matrix temp((*Inv) * (*m_B_t)); + double fac1 = (1.0/(16.0*QBALL_ANAL_RECON_PI*QBALL_ANAL_RECON_PI)); + switch(m_NormalizationMethod) + { + case QBAR_ADC_ONLY: + case QBAR_RAW_SIGNAL: + break; + case QBAR_STANDARD: + case QBAR_B_ZERO_B_VALUE: + case QBAR_B_ZERO: + case QBAR_NONE: + temp = (*P) * temp; + break; + case QBAR_SOLID_ANGLE: + temp = fac1 * (*P) * (*_L) * temp; + break; + case QBAR_NONNEG_SOLID_ANGLE: + break; + } - //tofile2(&temp,"A"); + //tofile2(&temp,"A"); - m_CoeffReconstructionMatrix = new vnl_matrix(m_NumberCoefficients,m_NumberOfGradientDirections); - for(int i=0; i(m_NumberCoefficients,m_NumberOfGradientDirections); + for(int i=0; iodfs later + // this code goes to the image adapter coeffs->odfs later - int NOdfDirections = NODF; - vnl_matrix_fixed* U = - itk::PointShell >::DistributePointShell(); + int NOdfDirections = NODF; + vnl_matrix_fixed* U = + itk::PointShell >::DistributePointShell(); - m_SphericalHarmonicBasisMatrix = new vnl_matrix(NOdfDirections,m_NumberCoefficients); - vnl_matrix* sphericalHarmonicBasisMatrix2 - = new vnl_matrix(NOdfDirections,m_NumberCoefficients); - for(int i=0; i(NOdfDirections,m_NumberCoefficients); + vnl_matrix* sphericalHarmonicBasisMatrix2 + = new vnl_matrix(NOdfDirections,m_NumberCoefficients); + for(int i=0; i(NOdfDirections,m_NumberOfGradientDirections); - *m_ReconstructionMatrix = (*m_SphericalHarmonicBasisMatrix) * (*m_CoeffReconstructionMatrix); - - } + m_ReconstructionMatrix = new vnl_matrix(NOdfDirections,m_NumberOfGradientDirections); + *m_ReconstructionMatrix = (*m_SphericalHarmonicBasisMatrix) * (*m_CoeffReconstructionMatrix); - template< class T, class TG, class TO, int L, int NODF> - void AnalyticalDiffusionQballReconstructionImageFilter - ::SetGradientImage( GradientDirectionContainerType *gradientDirection, - const GradientImagesType *gradientImage ) - { - this->m_GradientDirectionContainer = gradientDirection; +} - unsigned int numImages = gradientDirection->Size(); - this->m_NumberOfBaselineImages = 0; - for(GradientDirectionContainerType::Iterator it = this->m_GradientDirectionContainer->Begin(); - it != this->m_GradientDirectionContainer->End(); it++) +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::SetGradientImage( GradientDirectionContainerType *gradientDirection, + const GradientImagesType *gradientImage ) +{ + this->m_GradientDirectionContainer = gradientDirection; + + unsigned int numImages = gradientDirection->Size(); + this->m_NumberOfBaselineImages = 0; + for(GradientDirectionContainerType::Iterator it = this->m_GradientDirectionContainer->Begin(); + it != this->m_GradientDirectionContainer->End(); it++) + { + if(it.Value().one_norm() <= 0.0) { - if(it.Value().one_norm() <= 0.0) - { this->m_NumberOfBaselineImages++; - } - else // Normalize non-zero gradient directions - { - it.Value() = it.Value() / it.Value().two_norm(); - } } - - this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages; - - // ensure that the gradient image we received has as many components as - // the number of gradient directions - if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections ) + else // Normalize non-zero gradient directions { - itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages - << "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages - << " directions specified but image has " << gradientImage->GetVectorLength() - << " components."); + it.Value() = it.Value() / it.Value().two_norm(); } + } - this->ProcessObject::SetNthInput( 0, - const_cast< GradientImagesType* >(gradientImage) ); - - } + this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages; - template< class T, class TG, class TO, int L, int NODF> - void AnalyticalDiffusionQballReconstructionImageFilter - ::PrintSelf(std::ostream& os, Indent indent) const - { - std::locale C("C"); - std::locale originalLocale = os.getloc(); - os.imbue(C); + // ensure that the gradient image we received has as many components as + // the number of gradient directions + if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections ) + { + itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages + << "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages + << " directions specified but image has " << gradientImage->GetVectorLength() + << " components."); + } - Superclass::PrintSelf(os,indent); + this->ProcessObject::SetNthInput( 0, const_cast< GradientImagesType* >(gradientImage) ); +} - os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl; - if ( m_GradientDirectionContainer ) - { - os << indent << "GradientDirectionContainer: " - << m_GradientDirectionContainer << std::endl; - } - else - { - os << indent << - "GradientDirectionContainer: (Gradient directions not set)" << std::endl; - } - os << indent << "NumberOfGradientDirections: " << - m_NumberOfGradientDirections << std::endl; - os << indent << "NumberOfBaselineImages: " << - m_NumberOfBaselineImages << std::endl; - os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl; - os << indent << "BValue: " << m_BValue << std::endl; - - os.imbue( originalLocale ); - } +template< class T, class TG, class TO, int L, int NODF> +void AnalyticalDiffusionQballReconstructionImageFilter +::PrintSelf(std::ostream& os, Indent indent) const +{ + std::locale C("C"); + std::locale originalLocale = os.getloc(); + os.imbue(C); + + Superclass::PrintSelf(os,indent); + + os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl; + if ( m_GradientDirectionContainer ) + os << indent << "GradientDirectionContainer: " << m_GradientDirectionContainer << std::endl; + else + os << indent << "GradientDirectionContainer: (Gradient directions not set)" << std::endl; + + os << indent << "NumberOfGradientDirections: " << m_NumberOfGradientDirections << std::endl; + os << indent << "NumberOfBaselineImages: " << m_NumberOfBaselineImages << std::endl; + os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl; + os << indent << "BValue: " << m_BValue << std::endl; + os.imbue( originalLocale ); +} } #endif // __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp diff --git a/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h b/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h index c6ab682894..2a837f283a 100644 --- a/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h +++ b/Modules/DiffusionImaging/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h @@ -1,304 +1,282 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkAnalyticalDiffusionQballReconstructionImageFilter_h_ #define __itkAnalyticalDiffusionQballReconstructionImageFilter_h_ #include "itkImageToImageFilter.h" #include "vnl/vnl_vector_fixed.h" #include "vnl/vnl_matrix.h" #include "vnl/algo/vnl_svd.h" #include "itkVectorContainer.h" #include "itkVectorImage.h" namespace itk{ /** \class AnalyticalDiffusionQballReconstructionImageFilter * \brief This class takes as input one or more reference image (acquired in the * absence of diffusion sensitizing gradients) and 'n' diffusion * weighted images and their gradient directions and computes an image of * orientation distribution function coefficients in a spherical harmonic basis. * * \par Inputs and Usage * \par * When you have the 'n' gradient and one or more reference images in a single * multi-component image (VectorImage), you can specify the images as * \code * filter->SetGradientImage( directionsContainer, vectorImage ); * \endcode * Note that this method is used to specify both the reference and gradient images. * This is convenient when the DWI images are read in using the * NRRD * format. Like the Nrrd format, the reference images are those components of the * vectorImage whose gradient direction is (0,0,0). If more than one reference image * is present, they are averaged prior to the reconstruction. * * \par Outputs * The output image is an image of vectors that must be understood as ODFs: * \code * Image< Vector< TPixelType, OdfNrDirections >, 3 > * \endcode * * \par Parameters * \li Threshold - Threshold on the reference image data. The output ODF will * be a null pdf for pixels in the reference image that have a value less * than this. * \li BValue - See the documentation of SetBValue(). * \li At least 6 gradient images must be specified for the filter to be able * to run. If the input gradient directions g_i are majorly sampled on one half * of the sqhere, then each input image I_i will be duplicated and assign -g_i * in order to guarantee stability of the algorithm. * \li OdfDirections - directions of resulting orientation distribution function * \li EquatorNrSamplingPoints - number of sampling points on equator when * performing Funk Radeon Transform (FRT) * \li BasisFunctionCenters - the centers of the basis functions are used for * the sRBF (spherical radial basis functions interpolation). If not set, they * will be defaulted to equal m_EquatorNrSamplingPoints * * \par Template parameters * The class is templated over * \li the pixel type of the reference and gradient images * (expected to be scalar data types) * \li the internal representation of the ODF pixels (double, float etc). * \li the number of OdfDirections * \li the number of basis function centers for the sRBF * * \par References: * \li[1] * Tuch DS, * "Q-ball imaging", Magn Reson Med. 2004 Dec;52(6):1358-72. * */ template< class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections> class AnalyticalDiffusionQballReconstructionImageFilter : - public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >, - Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > + public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >, + Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > { public: - enum Normalization { - QBAR_STANDARD, - QBAR_B_ZERO_B_VALUE, - QBAR_B_ZERO, - QBAR_NONE, - QBAR_ADC_ONLY, - QBAR_RAW_SIGNAL, - QBAR_SOLID_ANGLE, - QBAR_NONNEG_SOLID_ANGLE - }; + enum Normalization { + QBAR_STANDARD, + QBAR_B_ZERO_B_VALUE, + QBAR_B_ZERO, + QBAR_NONE, + QBAR_ADC_ONLY, + QBAR_RAW_SIGNAL, + QBAR_SOLID_ANGLE, + QBAR_NONNEG_SOLID_ANGLE + }; - typedef AnalyticalDiffusionQballReconstructionImageFilter Self; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; - typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>, - Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > - Superclass; + typedef AnalyticalDiffusionQballReconstructionImageFilter Self; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>, + Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > Superclass; - /** Method for creation through the object factory. */ - itkNewMacro(Self); + /** Method for creation through the object factory. */ + itkNewMacro(Self) - /** Runtime information support. */ - itkTypeMacro(AnalyticalDiffusionQballReconstructionImageFilter, - ImageToImageFilter); + /** Runtime information support. */ + itkTypeMacro(AnalyticalDiffusionQballReconstructionImageFilter, ImageToImageFilter) - typedef TReferenceImagePixelType ReferencePixelType; + typedef TReferenceImagePixelType ReferencePixelType; - typedef TGradientImagePixelType GradientPixelType; + typedef TGradientImagePixelType GradientPixelType; - typedef Vector< TOdfPixelType, NrOdfDirections > OdfPixelType; + typedef Vector< TOdfPixelType, NrOdfDirections > OdfPixelType; - typedef TOdfPixelType BZeroPixelType; + typedef TOdfPixelType BZeroPixelType; - /** Reference image data, This image is aquired in the absence + /** Reference image data, This image is aquired in the absence * of a diffusion sensitizing field gradient */ - typedef typename Superclass::InputImageType ReferenceImageType; + typedef typename Superclass::InputImageType ReferenceImageType; - typedef Image< OdfPixelType, 3 > OdfImageType; + typedef Image< OdfPixelType, 3 > OdfImageType; - typedef OdfImageType OutputImageType; + typedef OdfImageType OutputImageType; - typedef Image< Vector< TOdfPixelType, (NOrderL*NOrderL + NOrderL + 2)/2 + NOrderL >, 3 > CoefficientImageType; + typedef Image< Vector< TOdfPixelType, (NOrderL*NOrderL + NOrderL + 2)/2 + NOrderL >, 3 > CoefficientImageType; - typedef Image< BZeroPixelType, 3 > BZeroImageType; + typedef Image< BZeroPixelType, 3 > BZeroImageType; - typedef typename Superclass::OutputImageRegionType - OutputImageRegionType; + typedef typename Superclass::OutputImageRegionType + OutputImageRegionType; - /** Typedef defining one (of the many) gradient images. */ - typedef Image< GradientPixelType, 3 > GradientImageType; + /** Typedef defining one (of the many) gradient images. */ + typedef Image< GradientPixelType, 3 > GradientImageType; - /** An alternative typedef defining one (of the many) gradient images. + /** An alternative typedef defining one (of the many) gradient images. * It will be assumed that the vectorImage has the same dimension as the * Reference image and a vector length parameter of \c n (number of * gradient directions)*/ - typedef VectorImage< GradientPixelType, 3 > GradientImagesType; + typedef VectorImage< GradientPixelType, 3 > GradientImagesType; - /** Holds the ODF reconstruction matrix */ - typedef vnl_matrix< TOdfPixelType >* - OdfReconstructionMatrixType; + /** Holds the ODF reconstruction matrix */ + typedef vnl_matrix< TOdfPixelType >* + OdfReconstructionMatrixType; - typedef vnl_matrix< double > CoefficientMatrixType; + typedef vnl_matrix< double > CoefficientMatrixType; - /** Holds each magnetic field gradient used to acquire one DWImage */ - typedef vnl_vector_fixed< double, 3 > GradientDirectionType; + /** Holds each magnetic field gradient used to acquire one DWImage */ + typedef vnl_vector_fixed< double, 3 > GradientDirectionType; - /** Container to hold gradient directions of the 'n' DW measurements */ - typedef VectorContainer< unsigned int, - GradientDirectionType > GradientDirectionContainerType; + /** Container to hold gradient directions of the 'n' DW measurements */ + typedef VectorContainer< unsigned int, + GradientDirectionType > GradientDirectionContainerType; - /** set method to add gradient directions and its corresponding + /** set method to add gradient directions and its corresponding * image. The image here is a VectorImage. The user is expected to pass the * gradient directions in a container. The ith element of the container * corresponds to the gradient direction of the ith component image the * VectorImage. For the baseline image, a vector of all zeros * should be set.*/ - void SetGradientImage( GradientDirectionContainerType *, - const GradientImagesType *image); + void SetGradientImage( GradientDirectionContainerType *, + const GradientImagesType *image); - /** Get reference image */ - virtual ReferenceImageType * GetReferenceImage() - { return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); } + /** Get reference image */ + virtual ReferenceImageType * GetReferenceImage() + { return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); } - /** Return the gradient direction. idx is 0 based */ - virtual GradientDirectionType GetGradientDirection( unsigned int idx) const + /** Return the gradient direction. idx is 0 based */ + virtual GradientDirectionType GetGradientDirection( unsigned int idx) const { - if( idx >= m_NumberOfGradientDirections ) - { - itkExceptionMacro( << "Gradient direction " << idx << "does not exist" ); - } - return m_GradientDirectionContainer->ElementAt( idx+1 ); + if( idx >= m_NumberOfGradientDirections ) + itkExceptionMacro( << "Gradient direction " << idx << "does not exist" ); + return m_GradientDirectionContainer->ElementAt( idx+1 ); } - static void tofile2(vnl_matrix *A, std::string fname); - static double factorial(int number); - static void Cart2Sph(double x, double y, double z, double* cart); - static double legendre0(int l); - static double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart); - static double Yj(int m, int k, double theta, double phi); + static void tofile2(vnl_matrix *A, std::string fname); + static void Cart2Sph(double x, double y, double z, double* cart); + static double Yj(int m, int k, double theta, double phi); + double Legendre0(int l); - OdfPixelType Normalize(OdfPixelType odf, typename NumericTraits::AccumulateType b0 ); + OdfPixelType Normalize(OdfPixelType odf, typename NumericTraits::AccumulateType b0 ); + vnl_vector PreNormalize( vnl_vector vec, typename NumericTraits::AccumulateType b0 ); - vnl_vector PreNormalize( vnl_vector vec, typename NumericTraits::AccumulateType b0 ); - - /** Threshold on the reference image data. The output ODF will be a null + /** Threshold on the reference image data. The output ODF will be a null * pdf for pixels in the reference image that have a value less than this * threshold. */ - itkSetMacro( Threshold, ReferencePixelType ); - itkGetMacro( Threshold, ReferencePixelType ); + itkSetMacro( Threshold, ReferencePixelType ) + itkGetMacro( Threshold, ReferencePixelType ) - itkSetMacro( NormalizationMethod, Normalization); - itkGetMacro( NormalizationMethod, Normalization ); + itkSetMacro( NormalizationMethod, Normalization) + itkGetMacro( NormalizationMethod, Normalization ) - typedef Image FloatImageType; - itkGetMacro( BZeroImage, typename BZeroImageType::Pointer); - itkGetMacro( ODFSumImage, typename FloatImageType::Pointer); - itkGetMacro( CoefficientImage, typename CoefficientImageType::Pointer); + typedef Image FloatImageType; + itkGetMacro( BZeroImage, typename BZeroImageType::Pointer) + itkGetMacro( ODFSumImage, typename FloatImageType::Pointer) + itkGetMacro( CoefficientImage, typename CoefficientImageType::Pointer) - itkSetMacro( BValue, TOdfPixelType); + itkSetMacro( BValue, TOdfPixelType) #ifdef GetBValue #undef GetBValue #endif - itkGetConstReferenceMacro( BValue, TOdfPixelType); - - itkSetMacro( Lambda, double ); - itkGetMacro( Lambda, double ); + itkGetConstReferenceMacro( BValue, TOdfPixelType) + itkSetMacro( Lambda, double ) + itkGetMacro( Lambda, double ) #ifdef ITK_USE_CONCEPT_CHECKING - /** Begin concept checking */ - itkConceptMacro(ReferenceEqualityComparableCheck, - (Concept::EqualityComparable)); - itkConceptMacro(TensorEqualityComparableCheck, - (Concept::EqualityComparable)); - itkConceptMacro(GradientConvertibleToDoubleCheck, - (Concept::Convertible)); - itkConceptMacro(DoubleConvertibleToTensorCheck, - (Concept::Convertible)); - itkConceptMacro(GradientReferenceAdditiveOperatorsCheck, - (Concept::AdditiveOperators)); - itkConceptMacro(ReferenceOStreamWritableCheck, - (Concept::OStreamWritable)); - itkConceptMacro(TensorOStreamWritableCheck, - (Concept::OStreamWritable)); - /** End concept checking */ + /** Begin concept checking */ + itkConceptMacro(ReferenceEqualityComparableCheck, + (Concept::EqualityComparable)); + itkConceptMacro(TensorEqualityComparableCheck, + (Concept::EqualityComparable)); + itkConceptMacro(GradientConvertibleToDoubleCheck, + (Concept::Convertible)); + itkConceptMacro(DoubleConvertibleToTensorCheck, + (Concept::Convertible)); + itkConceptMacro(GradientReferenceAdditiveOperatorsCheck, + (Concept::AdditiveOperators)); + itkConceptMacro(ReferenceOStreamWritableCheck, + (Concept::OStreamWritable)); + itkConceptMacro(TensorOStreamWritableCheck, + (Concept::OStreamWritable)); + /** End concept checking */ #endif protected: - AnalyticalDiffusionQballReconstructionImageFilter(); - ~AnalyticalDiffusionQballReconstructionImageFilter() {}; - void PrintSelf(std::ostream& os, Indent indent) const; + AnalyticalDiffusionQballReconstructionImageFilter(); + ~AnalyticalDiffusionQballReconstructionImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; - void ComputeReconstructionMatrix(); - - void BeforeThreadedGenerateData(); - void ThreadedGenerateData( const - OutputImageRegionType &outputRegionForThread, int); + void ComputeReconstructionMatrix(); + void BeforeThreadedGenerateData(); + void ThreadedGenerateData( const + OutputImageRegionType &outputRegionForThread, int); private: - OdfReconstructionMatrixType m_ReconstructionMatrix; - - OdfReconstructionMatrixType m_CoeffReconstructionMatrix; - - OdfReconstructionMatrixType m_SphericalHarmonicBasisMatrix; - - /** container to hold gradient directions */ - GradientDirectionContainerType::Pointer m_GradientDirectionContainer; - - /** Number of gradient measurements */ - unsigned int m_NumberOfGradientDirections; - - /** Number of baseline images */ - unsigned int m_NumberOfBaselineImages; - - /** Threshold on the reference image data */ - ReferencePixelType m_Threshold; - - /** LeBihan's b-value for normalizing tensors */ - TOdfPixelType m_BValue; - - typename BZeroImageType::Pointer m_BZeroImage; - - double m_Lambda; - - bool m_DirectionsDuplicated; - - Normalization m_NormalizationMethod; - - int m_NumberCoefficients; - - vnl_matrix* m_B_t; - vnl_vector* m_LP; - FloatImageType::Pointer m_ODFSumImage; - typename CoefficientImageType::Pointer m_CoefficientImage; - TOdfPixelType m_Delta1; - TOdfPixelType m_Delta2; + OdfReconstructionMatrixType m_ReconstructionMatrix; + OdfReconstructionMatrixType m_CoeffReconstructionMatrix; + OdfReconstructionMatrixType m_SphericalHarmonicBasisMatrix; + /** container to hold gradient directions */ + GradientDirectionContainerType::Pointer m_GradientDirectionContainer; + /** Number of gradient measurements */ + unsigned int m_NumberOfGradientDirections; + /** Number of baseline images */ + unsigned int m_NumberOfBaselineImages; + /** Threshold on the reference image data */ + ReferencePixelType m_Threshold; + /** LeBihan's b-value for normalizing tensors */ + TOdfPixelType m_BValue; + typename BZeroImageType::Pointer m_BZeroImage; + double m_Lambda; + bool m_DirectionsDuplicated; + Normalization m_NormalizationMethod; + int m_NumberCoefficients; + vnl_matrix* m_B_t; + vnl_vector* m_LP; + FloatImageType::Pointer m_ODFSumImage; + typename CoefficientImageType::Pointer m_CoefficientImage; + TOdfPixelType m_Delta1; + TOdfPixelType m_Delta2; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkAnalyticalDiffusionQballReconstructionImageFilter.cpp" #endif #endif //__itkAnalyticalDiffusionQballReconstructionImageFilter_h_ diff --git a/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp b/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp new file mode 100644 index 0000000000..e04b5e81c7 --- /dev/null +++ b/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp @@ -0,0 +1,1133 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef __itkDiffusionMultiShellQballReconstructionImageFilter_cpp +#define __itkDiffusionMultiShellQballReconstructionImageFilter_cpp + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +#include "mitkDiffusionFunctionCollection.h" +#include "itkPointShell.h" +#include + + +namespace itk { + +template< class T, class TG, class TO, int L, int NODF> +DiffusionMultiShellQballReconstructionImageFilter +::DiffusionMultiShellQballReconstructionImageFilter() : + m_GradientDirectionContainer(NULL), + m_NumberOfGradientDirections(0), + m_NumberOfBaselineImages(1), + m_Threshold(NumericTraits< ReferencePixelType >::NonpositiveMin()), + m_BValue(1.0), + m_Lambda(0.0), + m_IsHemisphericalArrangementOfGradientDirections(false), + m_IsArithmeticProgession(false), + m_ReconstructionType(Mode_Standard1Shell) +{ + // At least 1 inputs is necessary for a vector image. + // For images added one at a time we need at least six + this->SetNumberOfRequiredInputs( 1 ); +} + + +template +void DiffusionMultiShellQballReconstructionImageFilter +::Normalize( OdfPixelType & out) +{ + for(int i=0; i +double DiffusionMultiShellQballReconstructionImageFilter +::CalculateThreashold(const double value, const double delta) +{ + return (value<0)*(0.5*delta) + (value>=0 && value=delta && value<1-delta)*value+(value>=1-delta && value<1)*(1-0.5*delta-0.5*((1-value)*(1-value))/delta) + + (value>=1)*(1-0.5*delta); +} + +template +void DiffusionMultiShellQballReconstructionImageFilter +::Threshold(vnl_vector & vec, double delta) +{ + if (delta==0){ //Clip attenuation values. If att<0 => att=0, if att>1 => att=1 + for (int i=0; i=0 && vec[i]<=1)*vec[i]+(vec[i]>1); + } + else{ //Use function from Aganj et al, MRM, 2010 + for (int i=0; i< vec.size(); i++) + vec[i]=CalculateThreashold(vec[i], delta); + } +} + +template +void DiffusionMultiShellQballReconstructionImageFilter +::Threshold(vnl_matrix & mat, double delta) +{ + if (delta==0){ //Clip attenuation values. If att<0 => att=0, if att>1 => att=1 + for (int i=0; i=0 && mat(i,j)<=1)*mat(i,j)+(mat(i,j)>1); + } + else{ //Use function from Aganj et al, MRM, 2010 + for (int i=0; i +void DiffusionMultiShellQballReconstructionImageFilter +::Projection1( vnl_matrix & E, double delta ) +{ + + const double sF = sqrt(5.0); + + vnl_vector vOnes(E.rows()); + vOnes.fill(1.0); + + vnl_matrix T0(E.rows(), E.cols()); + vnl_matrix C(E.rows(), 7); + vnl_matrix A(E.rows(), 7); + vnl_matrix B(E.rows(), 7); + + vnl_vector s0(E.rows()); + vnl_vector a0(E.rows()); + vnl_vector b0(E.rows()); + vnl_vector ta(E.rows()); + vnl_vector tb(E.rows()); + vnl_vector e(E.rows()); + vnl_vector m(E.rows()); + vnl_vector a(E.rows()); + vnl_vector b(E.rows()); + + + // logarithmierung aller werte in E + for(int i = 0 ; i < E.rows(); i++) + { + for(int j = 0 ; j < E.cols(); j++) + { + T0(i,j) = -log(E(i,j)); + } + } + + + //T0 = -T0.apply(std::log); + + // Summeiere Zeilenweise über alle Shells sum = E1+E2+E3 + for(int i = 0 ; i < E.rows(); i++) + { + s0[i] = T0(i,0) + T0(i,1) + T0(i,2); + } + + + for(int i = 0; i < E.rows(); i ++) + { + // Alle Signal-Werte auf der Ersten shell E(N,0) normiert auf s0 + a0 = E(i,0) / s0[i]; + // Alle Signal-Werte auf der Zweiten shell E(N,1) normiert auf s0 + b0 = E(i,1) / s0[i]; + } + + ta = a0 * 3.0; + tb = b0 * 3.0; + e = tb - (ta * 2.0); + m = (tb * 2.0 ) + ta; + + for(int i = 0; i < E.rows(); i++) + { + C(i,0) = tb[i] < 1+3*delta && 0.5+1.5*(sF+1)*delta < ta[i] && ta[i] < 1-3* (sF+2) *delta; + C(i,1) = e[i] <= -1 +3*(2*sF+5)* delta && ta[i] >= 1-3*(sF+2)*delta; + C(i,2) = m[i] > 3 -3*sF*delta && -1+3*(2*sF+5)*delta < e[i] && e[i]<-3*sF*delta; + C(i,3) = m[i] >= 3-3*sF*delta && e[i] >= -3 *sF * delta; + C(i,4) = 2.5 + 1.5*(5+sF)*delta < m[i] && m[i] < 3-3*sF*delta && e[i] > -3*sF*delta; + C(i,5) = ta[i] <= 0.5+1.5 *(sF+1)*delta && m[i] <= 2.5 + 1.5 *(5+sF) * delta; + C(i,6) = !( C(i,0) || C(i,1) || C(i,2) || C(i,3) || C(i,4) || C(i,5) ); // ~ANY(C(i,[0-5] ),2) + + A(i,0)=(bool)C(i,0) * a0(i); + A(i,1)=(bool)C(i,1) * (1.0/3.0-(sF+2)*delta); + A(i,2)=(bool)C(i,2) * (0.2+0.8*a0(i)-0.4*b0(i)-delta/sF); + A(i,3)=(bool)C(i,3) * (0.2+delta/sF); + A(i,4)=(bool)C(i,4) * (0.2*a0(i)+0.4*b0(i)+2*delta/sF); + A(i,5)=(bool)C(i,5) * (1.0/6.0+0.5*(sF+1)*delta); + A(i,6)=(bool)C(i,6) * a0(i); + + B(i,0)=(bool)C(i,0) * (1.0/3.0+delta); + B(i,1)=(bool)C(i,1) * (1.0/3.0+delta); + B(i,2)=(bool)C(i,2) * (0.4-0.4*a0(i)+0.2*b0(i)-2*delta/sF); + B(i,3)=(bool)C(i,3) * (0.4-3*delta/sF); + B(i,4)=(bool)C(i,4) * (0.4*a0(i)+0.8*b0(i)-delta/sF); + B(i,5)=(bool)C(i,5) * (1.0/3.0+delta); + B(i,6)=(bool)C(i,6) * b0(i); + } + + + + for(int i = 0 ; i < E.rows(); i++) + { + double sumA = 0; + double sumB = 0; + for(int j = 0 ; j < 7; j++) + { + sumA += A(i,j); + sumB += B(i,j); + } + a[i] = sumA; + b[i] = sumB; + } + + for(int i = 0; i < E.rows(); i++) + { + E(i,0) = exp(-(a[i]*s0[i])); + E(i,1) = exp(-(b[i]*s0[i])); + E(i,2) = exp(-((1-a[i]-b[i])*s0[i])); + } + +} + + + + +template +void DiffusionMultiShellQballReconstructionImageFilter +::Projection2( vnl_vector & A, vnl_vector & a, vnl_vector & b, double delta0) +{ + + const double s6 = sqrt(6); + const double s15 = s6/2.0; + + vnl_vector delta(a.size()); + delta.fill(delta0); + + vnl_matrix AM(a.size(), 15); + vnl_matrix aM(a.size(), 15); + vnl_matrix bM(a.size(), 15); + vnl_matrix B(a.size(), 15); + + AM.set_column(0, A); + AM.set_column(1, A); + AM.set_column(2, A); + AM.set_column(3, delta); + AM.set_column(4, (A+a-b - (delta*s6))/3.0); + AM.set_column(5, delta); + AM.set_column(6, delta); + AM.set_column(7, delta); + AM.set_column(8, A); + AM.set_column(9, 0.2*(a*2+A-2*(s6+1)*delta)); + AM.set_column(10,0.2*(b*(-2)+A+2-2*(s6+1)*delta)); + AM.set_column(11, delta); + AM.set_column(12, delta); + AM.set_column(13, delta); + AM.set_column(14, 0.5-(1+s15)*delta); + + + aM.set_column(0, a); + aM.set_column(1, a); + aM.set_column(2, -delta + 1); + aM.set_column(3, a); + aM.set_column(4, (A*2+a*5+b+s6*delta)/6.0); + aM.set_column(5, a); + aM.set_column(6, -delta + 1); + aM.set_column(7, 0.5*(a+b)+(1+s15)*delta); + aM.set_column(8, -delta + 1); + aM.set_column(9, 0.2*(a*4+A*2+(s6+1)*delta)); + aM.set_column(10, -delta + 1); + aM.set_column(11, (s6+3)*delta); + aM.set_column(12, -delta + 1); + aM.set_column(13, -delta + 1); + aM.set_column(14, -delta + 1); + + bM.set_column(0, b); + bM.set_column(1, delta); + bM.set_column(2, b); + bM.set_column(3, b); + bM.set_column(4, (A*(-2)+a+b*5-s6*delta)/6.0); + bM.set_column(5, delta); + bM.set_column(6, b); + bM.set_column(7, 0.5*(a+b)-(1+s15)*delta); + bM.set_column(8, delta); + bM.set_column(9, delta); + bM.set_column(10, 0.2*(b*4-A*2+1-(s6+1)*delta)); + bM.set_column(11, delta); + bM.set_column(12, delta); + bM.set_column(13, -delta*(s6+3) + 1); + bM.set_column(14, delta); + + delta0 *= 0.99; + + for(int i = 0 ; i < a.size(); i ++) + { + for(int j = 0 ; j < 15; j ++) + { + B(i,j) = delta0 < AM(i,j) && 2 * (AM(i,j) + delta0 * s15) < aM(i,j) - bM(i,j) && bM(i,j) > delta0 && aM(i,j) < 1- delta0; + } + } + + vnl_matrix R2(a.size(), 15); + vnl_matrix A_(a.size(), 15); + vnl_matrix a_(a.size(), 15); + vnl_matrix b_(a.size(), 15); + + + + vnl_matrix OnesVecMat(1, 15); + OnesVecMat.fill(1.0); + + vnl_matrix AVecMat(a.size(), 1); + AVecMat.set_column(0,A); + + vnl_matrix aVecMat(a.size(), 1); + aVecMat.set_column(0,a); + + vnl_matrix bVecMat(a.size(), 1); + bVecMat.set_column(0,b); + + A_ = AM - (AVecMat * OnesVecMat); + a_ = aM - (aVecMat * OnesVecMat); + b_ = bM - (bVecMat * OnesVecMat); + + for(int i = 0 ; i < a.size(); i++) + for(int j = 0 ; j < 15; j++) + { + A_(i,j) *= A_(i,j); + a_(i,j) *= a_(i,j); + b_(i,j) *= b_(i,j); + } + + + R2 = A_ + a_ + b_; + + for(int i = 0 ; i < a.size(); i ++) + { + for(int j = 0 ; j < 15; j ++) + { + if(B(i,j) == 0) R2(i,j) = 1e20; + } + } + + std::vector indicies(a.size()); + + // suche den spalten-index der zu der kleinsten Zahl einer Zeile korrespondiert + for(int i = 0 ; i < a.size(); i++) + { + unsigned int index = 0; + double minvalue = 999; + for(int j = 0 ; j < 15 ; j++) + { + if(R2(i,j) < minvalue){ + minvalue = R2(i,j); + index = j; + } + } + indicies[i] = index; + } + + for(int i = 0 ; i < a.size(); i++) + { + A[i] = AM(i,indicies[i]); + a[i] = aM(i,indicies[i]); + b[i] = bM(i,indicies[i]); + } +} + + +template +void DiffusionMultiShellQballReconstructionImageFilter +::S_S0Normalization( vnl_vector & vec, typename NumericTraits::AccumulateType b0 ) +{ + + double b0f = (double)b0; + for(int i = 0; i < vec.size(); i++) + { + if (b0f==0) + b0f = 0.01; + if(vec[i] >= b0f) + vec[i] = b0f - 0.001; + vec[i] /= b0f; + } + +} + + +template +void DiffusionMultiShellQballReconstructionImageFilter +::S_S0Normalization( vnl_matrix & mat, typename NumericTraits::AccumulateType b0 ) +{ + double b0f = (double)b0; + for(int i = 0; i < mat.rows(); i++) + { + for( int j = 0; j < mat.cols(); j++ ){ + if (b0f==0) + b0f = 0.01; + if(mat(i,j) >= b0f) + mat(i,j) = b0f - 0.001; + mat(i,j) /= b0f; + } + } +} + + + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::DoubleLogarithm(vnl_vector & vec) +{ + for(int i = 0; i < vec.size(); i++) + { + vec[i] = log(-log(vec[i])); + } +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::SetGradientImage( GradientDirectionContainerType *gradientDirection + , const GradientImagesType *gradientImage + , float bvalue) +{ + this->m_BValue = bvalue; + this->m_GradientDirectionContainer = gradientDirection; + this->m_NumberOfBaselineImages = 0; + this->m_ReconstructionType = Mode_Standard1Shell; + + GradientDirectionContainerType::ConstIterator gdcit; + for( gdcit = this->m_GradientDirectionContainer->Begin(); gdcit != this->m_GradientDirectionContainer->End(); ++gdcit) + { + double bValueKey = int(((m_BValue* gdcit.Value().two_norm() * gdcit.Value().two_norm())+7.5)/10)*10; + m_GradientIndexMap[bValueKey].push_back(gdcit.Index()); + } + + //if(listOfUserSelctedBValues.size() == 0){ + // itkExceptionMacro(<< "DiffusionMultiShellQballReconstructionImageFilter.cpp : No list Of User Selcted B Values available"); + //} + if(m_GradientIndexMap.size() == 0){ + itkExceptionMacro(<< "DiffusionMultiShellQballReconstructionImageFilter.cpp : no GradientIndexMapAvalible"); + } + //if(listOfUserSelctedBValues.size() != m_GradientIndexMap.size()){ + // itkExceptionMacro(<< "DiffusionMultiShellQballReconstructionImageFilter.cpp : The number of user selected B Values != number of Image BValues"); + //} + + if(m_GradientIndexMap.size() == 4){ + + GradientIndexMapIteraotr it = m_GradientIndexMap.begin(); + it++; + const int b1 = (*it).first; + it++; + const int b2 = (*it).first; + it++; + const int b3 = (*it).first; + + if(b2 - b1 == b1 && b3 - b2 == b1 ) + { + m_ReconstructionType = Mode_Analytical3Shells; + } + } + + if(m_GradientIndexMap.size() > 2 && m_ReconstructionType != Mode_Analytical3Shells) + { + m_ReconstructionType = Mode_NumericalNShells; + } + + this->m_NumberOfBaselineImages = m_GradientIndexMap[0].size(); + this->m_NumberOfGradientDirections = gradientDirection->Size() - this->m_NumberOfBaselineImages; + + // ensure that the gradient image we received has as many components as + // the number of gradient directions + if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections ) + { + itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages + << "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages + << " directions specified but image has " << gradientImage->GetVectorLength() + << " components."); + } + + this->ProcessObject::SetNthInput( 0, const_cast< GradientImagesType* >(gradientImage) ); +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::BeforeThreadedGenerateData() +{ + itk::TimeProbe clock; + clock.Start(); + + if( m_NumberOfGradientDirections < (((L+1)*(L+2))/2) /* && m_NumberOfGradientDirections < 6 */ ) + { + itkExceptionMacro( << "At least " << ((L+1)*(L+2))/2 << " gradient directions are required" ); + } + // Input must be an itk::VectorImage. + std::string gradientImageClassName(this->ProcessObject::GetInput(0)->GetNameOfClass()); + + if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 ) + itkExceptionMacro( << "There is only one Gradient image. I expect that to be a VectorImage. But its of type: " << gradientImageClassName ); + + m_BZeroImage = BZeroImageType::New(); + typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); + m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing + m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin + m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction + m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion()); + m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() ); + m_BZeroImage->Allocate(); + + this->ComputeReconstructionMatrix(); + + clock.Stop(); + MITK_INFO << "Before GenerateData : " << clock.GetTotal(); + +} + + + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::StandardOneShellReconstruction(const OutputImageRegionType& outputRegionForThread) +{ + // Get output image pointer + typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); + + // ImageRegionIterator for the output image + ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); + oit.GoToBegin(); + + // ImageRegionIterator for the BZero (output) image + ImageRegionConstIterator< BZeroImageType > bzeroImageIterator(m_BZeroImage, outputRegionForThread); + bzeroImageIterator.GoToBegin(); + + IndiciesVector SignalIndicies = m_GradientIndexMap[1]; + + // if the gradient directiosn aragement is hemispherical, duplicate all gradient directions + // alone, interested in the value, the direction can be neglected + if(m_IsHemisphericalArrangementOfGradientDirections){ + int NumbersOfGradientIndicies = SignalIndicies.size(); + for (int i = 0 ; i < NumbersOfGradientIndicies; i++) + SignalIndicies.push_back(SignalIndicies[i]); + } + + + // Get input gradient image pointer + typename GradientImagesType::Pointer gradientImagePointer = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); + + // Const ImageRegionIterator for input gradient image + typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType; + GradientIteratorType git(gradientImagePointer, outputRegionForThread ); + git.GoToBegin(); + + typedef typename GradientImagesType::PixelType GradientVectorType; + + // iterate overall voxels of the gradient image region + while( ! git.IsAtEnd() ) + { + GradientVectorType b = git.Get(); + // ODF Vector + OdfPixelType odf(0.0); + + // Create the Signal Vector + vnl_vector SignalVector(m_NumberOfGradientDirections); + if( (bzeroImageIterator.Get() != 0) && (bzeroImageIterator.Get() >= m_Threshold) ) + { + + for( unsigned int i = 0; i< SignalIndicies.size(); i++ ) + { + SignalVector[i] = static_cast(b[SignalIndicies[i]]); + } + + // apply threashold an generate ln(-ln(E)) signal + // Replace SignalVector with PreNormalized SignalVector + S_S0Normalization(SignalVector, bzeroImageIterator.Get()); + DoubleLogarithm(SignalVector); + + // ODF coeffs-vector + vnl_vector coeffs(m_NumberCoefficients); + + // approximate ODF coeffs + coeffs = ( (*m_CoeffReconstructionMatrix) * SignalVector ); + coeffs[0] = 1.0/(2.0*sqrt(QBALL_ANAL_RECON_PI)); + + odf = mitk::vnl_function::element_cast(( (*m_ODFSphericalHarmonicBasisMatrix) * coeffs )).data_block(); + odf *= (QBALL_ANAL_RECON_PI*4/NODF); + } + // set ODF to ODF-Image + oit.Set( odf ); + ++oit; + ++bzeroImageIterator; + ++git; + + } + + MITK_INFO << "One Thread finished reconstruction"; +} + +#include +//#include +//#include + + + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::NumericalNShellReconstruction(const OutputImageRegionType& outputRegionForThread) +{ + + + // vnl_levenberg_marquardt LMOptimizer = new vnl_levenberg_marquardt(); + +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::GenerateAveragedBZeroImage(const OutputImageRegionType& outputRegionForThread) +{ + typedef typename GradientImagesType::PixelType GradientVectorType; + + ImageRegionIterator< BZeroImageType > bzeroIterator(m_BZeroImage, outputRegionForThread); + bzeroIterator.GoToBegin(); + + IndiciesVector BZeroIndicies = m_GradientIndexMap[0]; + + typename GradientImagesType::Pointer gradientImagePointer = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); + + // Const ImageRegionIterator for input gradient image + typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType; + GradientIteratorType git(gradientImagePointer, outputRegionForThread ); + git.GoToBegin(); + + + while( ! git.IsAtEnd() ) + { + GradientVectorType b = git.Get(); + + // compute the average bzero signal + typename NumericTraits::AccumulateType b0 = NumericTraits::Zero; + for(unsigned int i = 0; i < BZeroIndicies.size(); ++i) + { + b0 += b[BZeroIndicies[i]]; + } + b0 /= BZeroIndicies.size(); + + bzeroIterator.Set(b0); + ++bzeroIterator; + ++git; + } +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::AnalyticalThreeShellReconstruction(const OutputImageRegionType& outputRegionForThread) +{ + + typedef typename GradientImagesType::PixelType GradientVectorType; + + // Input Gradient Image and Output ODF Image + typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); + typename GradientImagesType::Pointer gradientImagePointer = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); + + + // Define Image iterators + ImageRegionIterator< OutputImageType > odfOutputImageIterator(outputImage, outputRegionForThread); + ImageRegionConstIterator< BZeroImageType > bzeroImageIterator(m_BZeroImage, outputRegionForThread); + ImageRegionConstIterator< GradientImagesType > gradientInputImageIterator(gradientImagePointer, outputRegionForThread ); + + // All iterators seht to Begin of the specific OutputRegion + odfOutputImageIterator.GoToBegin(); + bzeroImageIterator.GoToBegin(); + gradientInputImageIterator.GoToBegin(); + + // Get Shell Indicies for all non-BZero Gradients + // it MUST be a arithmetic progression eg.: 1000, 2000, 3000 + GradientIndexMapIteraotr it = m_GradientIndexMap.begin(); + it++; + // it = b-value = 1000 + IndiciesVector Shell1Indiecies = (*it).second; + it++; + // it = b-value = 2000 + IndiciesVector Shell2Indiecies = (*it).second; + it++; + // it = b-value = 3000 + IndiciesVector Shell3Indiecies = (*it).second; + + + // if input data is a hemispherical arragement, duplicate eache gradient for each shell + if(m_IsHemisphericalArrangementOfGradientDirections){ + int NumbersOfGradientIndicies = Shell1Indiecies.size(); + for (int i = 0 ; i < NumbersOfGradientIndicies; i++){ + Shell1Indiecies.push_back(Shell1Indiecies[i]); + Shell2Indiecies.push_back(Shell2Indiecies[i]); + Shell3Indiecies.push_back(Shell3Indiecies[i]); + } + } + + // Nx3 Signal Vector with E(0) = Shell 1, E(1) = Shell 2, E(2) = Shell 3 + vnl_matrix< double > * E = new vnl_matrix(Shell1Indiecies.size(), 3); + + vnl_vector * AlphaValues = new vnl_vector(Shell1Indiecies.size()); + vnl_vector * BetaValues = new vnl_vector(Shell1Indiecies.size()); + vnl_vector * LAValues = new vnl_vector(Shell1Indiecies.size()); + vnl_vector * PValues = new vnl_vector(Shell1Indiecies.size()); + + OdfPixelType odf(0.0); + + // iterate overall voxels of the gradient image region + while( ! gradientInputImageIterator.IsAtEnd() ) + { + if( (bzeroImageIterator.Get() != 0) && (bzeroImageIterator.Get() >= m_Threshold) ) + { + // Get the Signal-Value for each Shell at each direction (specified in the ShellIndicies Vector .. this direction corresponse to this shell...) + GradientVectorType b = gradientInputImageIterator.Get(); + for(int i = 0 ; i < Shell1Indiecies.size(); i++) + { + E->put(i,0, static_cast(b[Shell1Indiecies[i]])); + E->put(i,1, static_cast(b[Shell2Indiecies[i]])); + E->put(i,2, static_cast(b[Shell3Indiecies[i]])); + } + + //Approximated-Signal by SH fit - using the specific shell directions and values + // approximated Signal : S = SHBasis * Coeffs + // with Coeffs : C = (B_T * B + lambda * L) ^ -1 * B_T * OS + // OS := Original-Signal + E->set_column(1, (*m_SHBasisMatrix) * ((*m_SignalReonstructionMatrix) * (E->get_column(1)))); + E->set_column(2, (*m_SHBasisMatrix) * ((*m_SignalReonstructionMatrix) * (E->get_column(2)))); + + // Normalize the Signal: Si/S0 + S_S0Normalization(*E,bzeroImageIterator.Get()); + + //Implements Eq. [19] and Fig. 4. + Threshold(*E); + + //inqualities [31]. Taking the lograithm of th first tree inqualities + //convert the quadratic inqualities to linear ones. + Projection1(*E); + + double E1, E2, E3, P2,A,B2,B,P,alpha,beta,lambda, ER1, ER2; + + for( unsigned int i = 0; i< Shell1Indiecies.size(); i++ ) + { + + E1 = E->get(i,0); + E2 = E->get(i,1); + E3 = E->get(i,2); + + P2 = E2-E1*E1; + A = (E3 -E1*E2) / ( 2* P2); + B2 = A * A -(E1 * E3 - E2 * E2) /P2; + B = 0; + if(B2 > 0) B = sqrt(B2); + + P = 0; + if(P2 > 0) P = sqrt(P2); + + alpha = A + B; + beta = A - B; + + + lambda = 0.5 + 0.5 * std::sqrt(1 - std::pow((P * 2 ) / (alpha - beta), 2));; + ER1 = std::fabs(lambda * (alpha - beta) + (beta - E1 )) + + std::fabs(lambda * (std::pow(alpha, 2) - std::pow(beta, 2)) + (std::pow(beta, 2) - E2 )) + + std::fabs(lambda * (std::pow(alpha, 3) - std::pow(beta, 3)) + (std::pow(beta, 3) - E3 )); + ER2 = std::fabs((lambda-1) * (alpha - beta) + (beta - E1 )) + + std::fabs((lambda-1) * (std::pow(alpha, 2) - std::pow(beta, 2)) + (std::pow(beta, 2) - E2 )) + + std::fabs((lambda-1) * (std::pow(alpha, 3) - std::pow(beta, 3)) + (std::pow(beta, 3) - E3 )); + + + PValues->put(i, P); + AlphaValues->put(i, alpha); + BetaValues->put(i, beta); + LAValues->put(i,(lambda * (ER1 < ER2)) + ((1-lambda) * (ER1 >= ER2))); + + } + Projection2(*PValues, *AlphaValues, *BetaValues); + + //Threshold(*AlphaValues); + //Threshold(*BetaValues); + + DoubleLogarithm(*AlphaValues); + DoubleLogarithm(*BetaValues); + + vnl_vector SignalVector(element_product((*LAValues) , (*AlphaValues)-(*BetaValues)) + (*BetaValues)); + vnl_vector coeffs((*m_CoeffReconstructionMatrix) *SignalVector ); + + // the first coeff is a fix value + coeffs[0] = 1.0/(2.0*sqrt(QBALL_ANAL_RECON_PI)); + + // Cast the Signal-Type from double to float for the ODF-Image + odf = mitk::vnl_function::element_cast( (*m_ODFSphericalHarmonicBasisMatrix) * coeffs ).data_block(); + odf *= (QBALL_ANAL_RECON_PI*4/NODF); + //Normalize(odf); + } + + // set ODF to ODF-Image + odfOutputImageIterator.Set( odf ); + ++odfOutputImageIterator; + // iterate + ++bzeroImageIterator; + ++gradientInputImageIterator; + } + + + + MITK_INFO << "THREAD FINISHED"; + delete E; + delete AlphaValues; + delete BetaValues; + delete PValues; + delete LAValues; +} + + +template< class T, class TG, class TO, int L, int NODF> +vnl_vector DiffusionMultiShellQballReconstructionImageFilter +::AnalyticalThreeShellParameterEstimation(const IndiciesVector * shell1Indicies,const IndiciesVector * shell2Indicies ,const IndiciesVector * shell3Indicies, vnl_vector) +{ + + + +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int NumberOfThreads) +{ + itk::TimeProbe clock; + + GenerateAveragedBZeroImage(outputRegionForThread); + + clock.Start(); + switch(m_ReconstructionType) + { + case Mode_Standard1Shell: + StandardOneShellReconstruction(outputRegionForThread); + break; + case Mode_Analytical3Shells: + AnalyticalThreeShellReconstruction(outputRegionForThread); + break; + case Mode_NumericalNShells: + break; + } + clock.Stop(); + MITK_INFO << "Reconstruction in : " << clock.GetTotal() << " TU"; + + + +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter:: +ComputeSphericalHarmonicsBasis(vnl_matrix * QBallReference, vnl_matrix *SHBasisOutput, vnl_matrix* LaplaciaBaltramiOutput, vnl_vector* SHOrderAssociation, vnl_matrix* SHEigenvalues ) +{ + for(unsigned int i=0; i< (*SHBasisOutput).rows(); i++) + { + for(int k = 0; k <= L; k += 2) + { + for(int m =- k; m <= k; m++) + { + int j = ( k * k + k + 2 ) / 2 + m - 1; + + // Compute SHBasisFunctions + double phi = (*QBallReference)(0,i); + double th = (*QBallReference)(1,i); + (*SHBasisOutput)(i,j) = mitk::sh::Yj(m,k,th,phi); + + // Laplacian Baltrami Order Association + if(LaplaciaBaltramiOutput) + (*LaplaciaBaltramiOutput)(j,j) = k*k*(k + 1)*(k+1); + + // SHEigenvalues with order Accosiation kj + if(SHEigenvalues) + (*SHEigenvalues)(j,j) = -k* (k+1); + + // Order Association + if(SHOrderAssociation) + (*SHOrderAssociation)[j] = k; + + } + } + } +} + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::ComputeFunkRadonTransformationMatrix(vnl_vector* SHOrderAssociationReference, vnl_matrix* FRTMatrixOutput ) +{ + for(int i=0; i +bool DiffusionMultiShellQballReconstructionImageFilter +::CheckHemisphericalArrangementOfGradientDirections() +{ + // handle acquisition schemes where only half of the spherical + // shell is sampled by the gradient directions. In this case, + // each gradient direction is duplicated in negative direction. + vnl_vector centerMass(3); + centerMass.fill(0.0); + int count = 0; + GradientDirectionContainerType::ConstIterator gdcit1; + for( gdcit1 = this->m_GradientDirectionContainer->Begin(); gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1) + { + if(gdcit1.Value().one_norm() > 0.0) + { + centerMass += gdcit1.Value(); + count ++; + } + } + centerMass /= count; + if(centerMass.two_norm() > 0.1) + { + return false; + } + return true; +} + +template< class T, class TG, class TO, int L, int NOdfDirections> +void DiffusionMultiShellQballReconstructionImageFilter +::ComputeReconstructionMatrix() +{ + + typedef std::auto_ptr< vnl_matrix< double> > MatrixDoublePtr; + typedef std::auto_ptr< vnl_vector< int > > VectorIntPtr; + typedef std::auto_ptr< vnl_matrix_inverse< double > > InverseMatrixDoublePtr; + + std::map >::const_iterator it = (m_GradientIndexMap.begin()); + it++; + const std::vector gradientIndiciesVector= (*it).second; + + int numberOfGradientDirections = gradientIndiciesVector.size(); + + + if( numberOfGradientDirections < (((L+1)*(L+2))/2) || numberOfGradientDirections < 6 ) + { + itkExceptionMacro( << "At least (L+1)(L+2)/2 gradient directions for each shell are required; current : " << numberOfGradientDirections ); + } + + + CheckDuplicateDiffusionGradients(); + + // check if gradient directions are arrangement as a hemisphere(true) or sphere(false) + m_IsHemisphericalArrangementOfGradientDirections = CheckHemisphericalArrangementOfGradientDirections(); + if(m_IsHemisphericalArrangementOfGradientDirections) numberOfGradientDirections *= 2; + + + MatrixDoublePtr Q(new vnl_matrix(3, numberOfGradientDirections)); + Q->fill(0.0); + // Cartesian to spherical coordinates + { + int j = 0; + + for(int i = 0; i < gradientIndiciesVector.size(); i++) + { + + double x = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(0); + double y = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(1); + double z = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(2); + double cart[3]; + mitk::sh::Cart2Sph(x,y,z,cart); + (*Q)(0,j) = cart[0]; + (*Q)(1,j) = cart[1]; + (*Q)(2,j++) = cart[2]; + + } + if(m_IsHemisphericalArrangementOfGradientDirections) + { + for(int i = 0; i < gradientIndiciesVector.size(); i++) + { + double x = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(0); + double y = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(1); + double z = this->m_GradientDirectionContainer->ElementAt(gradientIndiciesVector[i]).get(2); + double cart[3]; + mitk::sh::Cart2Sph(x,y,z,cart); + (*Q)(0,j) = cart[0]; + (*Q)(1,j) = cart[1]; + (*Q)(2,j++) = cart[2]; + } + } + } + + const int LOrder = L; + m_NumberCoefficients = (int)(LOrder*LOrder + LOrder + 2.0)/2.0 + LOrder; + MITK_INFO << m_NumberCoefficients; + m_SHBasisMatrix = new vnl_matrix(numberOfGradientDirections,m_NumberCoefficients); + m_SHBasisMatrix->fill(0.0); + VectorIntPtr SHOrderAssociation(new vnl_vector(m_NumberCoefficients)); + SHOrderAssociation->fill(0.0); + MatrixDoublePtr LaplacianBaltrami(new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients)); + LaplacianBaltrami->fill(0.0); + MatrixDoublePtr FRTMatrix(new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients)); + FRTMatrix->fill(0.0); + MatrixDoublePtr SHEigenvalues(new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients)); + SHEigenvalues->fill(0.0); + + + + // SHBasis-Matrix + LaplacianBaltrami-Matrix + SHOrderAssociationVector + ComputeSphericalHarmonicsBasis(Q.get() ,m_SHBasisMatrix, LaplacianBaltrami.get(), SHOrderAssociation.get(), SHEigenvalues.get()); + + // Compute FunkRadon Transformation Matrix Associated to SHBasis Order lj + ComputeFunkRadonTransformationMatrix(SHOrderAssociation.get() ,FRTMatrix.get()); + + MatrixDoublePtr temp(new vnl_matrix(((m_SHBasisMatrix->transpose()) * (*m_SHBasisMatrix)) + (m_Lambda * (*LaplacianBaltrami)))); + + InverseMatrixDoublePtr pseudo_inv(new vnl_matrix_inverse((*temp))); + MatrixDoublePtr inverse(new vnl_matrix(m_NumberCoefficients,m_NumberCoefficients)); + inverse->fill(0.0); + (*inverse) = pseudo_inv->inverse(); + + // ODF Factor ( missing 1/4PI ?? ) + double factor = (1.0/(16.0*QBALL_ANAL_RECON_PI*QBALL_ANAL_RECON_PI)); + + m_SignalReonstructionMatrix = new vnl_matrix((*inverse) * (m_SHBasisMatrix->transpose())); + + m_CoeffReconstructionMatrix = new vnl_matrix(( factor * ((*FRTMatrix) * ((*SHEigenvalues) * (*m_SignalReonstructionMatrix))) )); + + // this code goes to the image adapter coeffs->odfs later + + vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); + + m_ODFSphericalHarmonicBasisMatrix = new vnl_matrix(NOdfDirections,m_NumberCoefficients); + m_ODFSphericalHarmonicBasisMatrix->fill(0.0); + + for(int i=0; i +template< class VNLType > +void DiffusionMultiShellQballReconstructionImageFilter +::printMatrix( VNLType * mat ) +{ + + std::stringstream stream; + + for(int i = 0 ; i < mat->rows(); i++) + { + stream.str(""); + for(int j = 0; j < mat->cols(); j++) + { + stream << (*mat)(i,j) << " "; + } + + } + MITK_INFO << stream.str(); +} + +template< class T, class TG, class TO, int L, int NODF> +bool DiffusionMultiShellQballReconstructionImageFilter +::CheckDuplicateDiffusionGradients() +{ + bool value = false; + + GradientIndexMapIteraotr mapIterator = m_GradientIndexMap.begin(); + while(mapIterator != m_GradientIndexMap.end()) + { + std::vector::const_iterator it1 = mapIterator->second.begin(); + std::vector::const_iterator it2 = mapIterator->second.begin(); + + for(; it1 != mapIterator->second.end(); ++it1) + { + for(; it2 != mapIterator->second.end(); ++it2) + { + if(m_GradientDirectionContainer->ElementAt(*it1) == m_GradientDirectionContainer->ElementAt(*it2) && it1 != it2) + { + itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." ); + value = true; + } + } + } + ++mapIterator; + } + return value; +} + + +template< class T, class TG, class TO, int L, int NODF> +void DiffusionMultiShellQballReconstructionImageFilter +::PrintSelf(std::ostream& os, Indent indent) const +{ + std::locale C("C"); + std::locale originalLocale = os.getloc(); + os.imbue(C); + + Superclass::PrintSelf(os,indent); + + //os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl; + if ( m_GradientDirectionContainer ) + { + os << indent << "GradientDirectionContainer: " + << m_GradientDirectionContainer << std::endl; + } + else + { + os << indent << + "GradientDirectionContainer: (Gradient directions not set)" << std::endl; + } + os << indent << "NumberOfGradientDirections: " << + m_NumberOfGradientDirections << std::endl; + os << indent << "NumberOfBaselineImages: " << + m_NumberOfBaselineImages << std::endl; + os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl; + os << indent << "BValue: " << m_BValue << std::endl; + + os.imbue( originalLocale ); +} + + + + +} + +#endif // __itkDiffusionMultiShellQballReconstructionImageFilter_cpp diff --git a/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h b/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h new file mode 100644 index 0000000000..88ad2d65a9 --- /dev/null +++ b/Modules/DiffusionImaging/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h @@ -0,0 +1,215 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __itkDiffusionMultiShellQballReconstructionImageFilter_h_ +#define __itkDiffusionMultiShellQballReconstructionImageFilter_h_ + +#include "itkImageToImageFilter.h" +#include "vnl/vnl_vector_fixed.h" +#include "vnl/vnl_matrix.h" +#include "vnl/algo/vnl_svd.h" +#include "itkVectorContainer.h" +#include "itkVectorImage.h" +#include + + + +namespace itk{ +/** \class DiffusionMultiShellQballReconstructionImageFilter + Aganj_2010 + */ + +template< class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections> +class DiffusionMultiShellQballReconstructionImageFilter : public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >, Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > +{ + +public: + + typedef DiffusionMultiShellQballReconstructionImageFilter Self; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>, Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > Superclass; + typedef TReferenceImagePixelType ReferencePixelType; + typedef TGradientImagePixelType GradientPixelType; + typedef Vector< TOdfPixelType, NrOdfDirections > OdfPixelType; + typedef typename Superclass::InputImageType ReferenceImageType; + typedef Image< OdfPixelType, 3 > OdfImageType; + typedef OdfImageType OutputImageType; + typedef TOdfPixelType BZeroPixelType; + typedef Image< BZeroPixelType, 3 > BZeroImageType; + typedef typename Superclass::OutputImageRegionType OutputImageRegionType; + /** Typedef defining one (of the many) gradient images. */ + typedef Image< GradientPixelType, 3 > GradientImageType; + /** An alternative typedef defining one (of the many) gradient images. + * It will be assumed that the vectorImage has the same dimension as the + * Reference image and a vector length parameter of \c n (number of + * gradient directions)*/ + typedef VectorImage< GradientPixelType, 3 > GradientImagesType; + /** Holds the ODF reconstruction matrix */ + typedef vnl_matrix< TOdfPixelType >* OdfReconstructionMatrixType; + typedef vnl_matrix< double > * CoefficientMatrixType; + /** Holds each magnetic field gradient used to acquire one DWImage */ + typedef vnl_vector_fixed< double, 3 > GradientDirectionType; + /** Container to hold gradient directions of the 'n' DW measurements */ + typedef VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; + + typedef std::map > GradientIndexMap; + typedef std::map >::iterator GradientIndexMapIteraotr; + typedef std::vector IndiciesVector; + + // --------------------------------------------------------------------------------------------// + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(DiffusionMultiShellQballReconstructionImageFilter, ImageToImageFilter); + + /** set method to add gradient directions and its corresponding + * image. The image here is a VectorImage. The user is expected to pass the + * gradient directions in a container. The ith element of the container + * corresponds to the gradient direction of the ith component image the + * VectorImage. For the baseline image, a vector of all zeros + * should be set.*/ + void SetGradientImage( GradientDirectionContainerType *, const GradientImagesType *image , float bvalue);//, std::vector listOfUserSelctedBValues ); + + + /** Get reference image */ + virtual ReferenceImageType * GetReferenceImage() + { return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); } + + /** Return the gradient direction. idx is 0 based */ + virtual GradientDirectionType GetGradientDirection( unsigned int idx) const + { + if( idx >= m_GradientDirectionContainer->Size() ) + { + itkExceptionMacro( << "Gradient direction " << idx << "does not exist" ); + } + return m_GradientDirectionContainer->ElementAt( idx+1 ); + } + + void Normalize(OdfPixelType & odf ); + + void S_S0Normalization( vnl_vector & vec, typename NumericTraits::AccumulateType b0 = 0 ); + void S_S0Normalization( vnl_matrix & mat, typename NumericTraits::AccumulateType b0 = 0 ); + + void DoubleLogarithm(vnl_vector & vec); + + void Threshold(vnl_vector & vec, double delta = 0.01); + void Threshold(vnl_matrix & mat, double delta = 0.01); + double CalculateThreashold(const double value, const double delta); + + void Projection1( vnl_matrix & mat, double delta = 0.01); + void Projection2( vnl_vector & A, vnl_vector & alpha, vnl_vector & beta, double delta = 0.01); + + /** Threshold on the reference image data. The output ODF will be a null + * pdf for pixels in the reference image that have a value less than this + * threshold. */ + itkSetMacro( Threshold, ReferencePixelType ); + itkGetMacro( Threshold, ReferencePixelType ); + + itkGetMacro( BZeroImage, typename BZeroImageType::Pointer); + //itkGetMacro( ODFSumImage, typename BlaImage::Pointer); + + itkSetMacro( Lambda, double ); + itkGetMacro( Lambda, double ); + + itkGetConstReferenceMacro( BValue, TOdfPixelType); + + +protected: + DiffusionMultiShellQballReconstructionImageFilter(); + ~DiffusionMultiShellQballReconstructionImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + void ComputeReconstructionMatrix(); + bool CheckDuplicateDiffusionGradients(); + void ComputeSphericalHarmonicsBasis(vnl_matrix* QBallReference, vnl_matrix* SHBasisOutput, vnl_matrix* LaplaciaBaltramiOutput, vnl_vector* SHOrderAssociation , vnl_matrix * SHEigenvalues); + void ComputeFunkRadonTransformationMatrix(vnl_vector* SHOrderAssociationReference, vnl_matrix* FRTMatrixOutput ); + bool CheckHemisphericalArrangementOfGradientDirections(); + + void BeforeThreadedGenerateData(); + void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, int NumberOfThreads ); + + vnl_vector AnalyticalThreeShellParameterEstimation(const IndiciesVector * shell1, const IndiciesVector * shell2, const IndiciesVector * shell3, vnl_vector b); + void StandardOneShellReconstruction(const OutputImageRegionType& outputRegionForThread); + void AnalyticalThreeShellReconstruction(const OutputImageRegionType& outputRegionForThread); + void NumericalNShellReconstruction(const OutputImageRegionType& outputRegionForThread); + void GenerateAveragedBZeroImage(const OutputImageRegionType& outputRegionForThread); + +private: + + enum ReconstructionType + { + Mode_Analytical3Shells, + Mode_NumericalNShells, + Mode_Standard1Shell + }; + + + + //CoefficientMatrixType m_ReconstructionMatrix; + CoefficientMatrixType m_CoeffReconstructionMatrix; + CoefficientMatrixType m_ODFSphericalHarmonicBasisMatrix; + CoefficientMatrixType m_SignalReonstructionMatrix; + CoefficientMatrixType m_SHBasisMatrix; + + /** container to hold gradient directions */ + GradientDirectionContainerType::Pointer m_GradientDirectionContainer; + + /** Number of gradient measurements */ + unsigned int m_NumberOfGradientDirections; + + /** Number of baseline images */ + unsigned int m_NumberOfBaselineImages; + + /** Threshold on the reference image data */ + ReferencePixelType m_Threshold; + + /** LeBihan's b-value for normalizing tensors */ + float m_BValue; + + typename BZeroImageType::Pointer m_BZeroImage; + + GradientIndexMap m_GradientIndexMap; + + double m_Lambda; + + bool m_IsHemisphericalArrangementOfGradientDirections; + + bool m_IsArithmeticProgession; + + int m_NumberCoefficients; + + ReconstructionType m_ReconstructionType; + + + + template< class VNLType > + void printMatrix( VNLType * mat ); + + + +}; + +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkDiffusionMultiShellQballReconstructionImageFilter.cpp" +#endif + +#endif //__itkDiffusionMultiShellQballReconstructionImageFilter_h_ + diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp index 5ac6db6694..7553f0129b 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp @@ -1,321 +1,336 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /* * mitkFiberBundleMapper2D.cpp * mitk-all * * Created by HAL9000 on 1/17/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkFiberBundleXMapper2D.h" #include #include #include #include #include //#include //#include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() { } mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundleX * > ( GetData() ); } void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) { if ( !this->IsVisible( renderer ) ) { return; } MITK_DEBUG << "MapperFBX 2D update: "; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { // MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateDataForRenderer( renderer ); } if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning) { this->UpdateShaderParameter(renderer); } } void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get information about current position of views mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); //generate according cutting planes based on the view position float sliceN[3], planeOrigin[3]; // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates planeOrigin[0] = (float) planeGeo->GetOrigin()[0]; planeOrigin[1] = (float) planeGeo->GetOrigin()[1]; planeOrigin[2] = (float) planeGeo->GetOrigin()[2]; sliceN[0] = planeGeo->GetNormal()[0]; sliceN[1] = planeGeo->GetNormal()[1]; sliceN[2] = planeGeo->GetNormal()[2]; float tmp1 = planeOrigin[0] * sliceN[0]; float tmp2 = planeOrigin[1] * sliceN[1]; float tmp3 = planeOrigin[2] * sliceN[2]; float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector float plane1[4]; plane1[0] = sliceN[0]; plane1[1] = sliceN[1]; plane1[2] = sliceN[2]; plane1[3] = d1; float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; int fiberfading_i = 1; if (!fiberfading) fiberfading_i = 0; // set Opacity float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1, &fiberfading_i); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberOpacity", 1, &fiberOpacity); } // ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE. // vtkActors and Mappers are feeded here void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //this procedure is depricated, //not needed after initializaton anymore mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) { MITK_INFO << "check DATANODE: ....[Fail] "; return; } /////////////////////////////////// ///THIS GET INPUT mitk::FiberBundleX* fbx = this->GetInput(); localStorage->m_PointMapper->ScalarVisibilityOn(); localStorage->m_PointMapper->SetScalarModeToUsePointFieldData(); localStorage->m_PointMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); // set color if (fbx->GetCurrentColorCoding() != NULL){ // localStorage->m_PointMapper->SelectColorArray(""); localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding()); MITK_DEBUG << "MapperFBX 2D: " << fbx->GetCurrentColorCoding(); if(fbx->GetCurrentColorCoding() == fbx->COLORCODING_CUSTOM){ float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_PointActor->GetProperty()->SetColor(trgb); } } localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData()); localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); // Applying shading properties { mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime); } this->UpdateShaderParameter(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)"; this->Update(renderer); return m_LSH.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { //add shader to datano //####### load shader from file ######### QString applicationDir = QCoreApplication::applicationDirPath(); if (applicationDir.endsWith("bin")) applicationDir.append("/"); else if (applicationDir.endsWith("MacOS")) { //on osx, check if path for installer or MITK development is needed applicationDir.append("/"); QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" ); if( !f.exists() ) // if file does not exist, then look in MITK development build directory applicationDir.append("../../../"); }else applicationDir.append("\\..\\"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository(); shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml")); //#################################################################### node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } // following methods are essential, they actually call the GetVtkProp() method // which returns the desired actors void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)"; if ( this->IsVisible(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)"; if ( this->IsVisible( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)"; if ( this->IsVisible(renderer)==false ) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)"; if(IsVisible(renderer)==false) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); } mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_PointMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/Testing/CMakeLists.txt b/Modules/DiffusionImaging/Testing/CMakeLists.txt index 153cd81e2e..27763457ee 100644 --- a/Modules/DiffusionImaging/Testing/CMakeLists.txt +++ b/Modules/DiffusionImaging/Testing/CMakeLists.txt @@ -1 +1,4 @@ MITK_CREATE_MODULE_TESTS() + +mitkAddCustomModuleTest(mitkFiberBundleXReaderWriterTest mitkFiberBundleXReaderWriterTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib) +mitkAddCustomModuleTest(mitkFiberBundleXTest mitkFiberBundleXTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib) diff --git a/Modules/DiffusionImaging/Testing/files.cmake b/Modules/DiffusionImaging/Testing/files.cmake index dad71c0c83..545e2e6ab2 100644 --- a/Modules/DiffusionImaging/Testing/files.cmake +++ b/Modules/DiffusionImaging/Testing/files.cmake @@ -1,3 +1,8 @@ -set(MODULE_TESTS +SET(MODULE_TESTS mitkFactoryRegistrationTest.cpp ) + +SET(MODULE_CUSTOM_TESTS + mitkFiberBundleXReaderWriterTest.cpp + mitkFiberBundleXTest.cpp +) diff --git a/Modules/DiffusionImaging/Testing/mitkFiberBundleXReaderWriterTest.cpp b/Modules/DiffusionImaging/Testing/mitkFiberBundleXReaderWriterTest.cpp new file mode 100644 index 0000000000..b4ea260f0d --- /dev/null +++ b/Modules/DiffusionImaging/Testing/mitkFiberBundleXReaderWriterTest.cpp @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/**Documentation + * Test for fiber bundle reader and writer + */ +int mitkFiberBundleXReaderWriterTest(int argc, char* argv[]) +{ + MITK_TEST_BEGIN("mitkFiberBundleXReaderWriterTest"); + + MITK_TEST_CONDITION_REQUIRED(argc>1,"check for fielename") + + mitk::FiberBundleXReader::Pointer reader = mitk::FiberBundleXReader::New(); + mitk::FiberBundleXWriter::Pointer writer = mitk::FiberBundleXWriter::New(); + mitk::FiberBundleX::Pointer fib1; + mitk::FiberBundleX::Pointer fib2; + + // first test: did this work? + // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since + // it makes no sense to continue without an object. + MITK_TEST_CONDITION_REQUIRED(reader.IsNotNull(),"reader instantiation") + MITK_TEST_CONDITION_REQUIRED(writer.IsNotNull(),"writer instantiation") + + try{ + RegisterDiffusionImagingObjectFactory(); + + // test if fib1 can be read + const std::string s1="", s2=""; + std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[1], s1, s2, false ); + mitk::BaseData::Pointer baseData = fibInfile.at(0); + fib1 = dynamic_cast(baseData.GetPointer()); + MITK_TEST_CONDITION_REQUIRED(fib1.IsNotNull(),"check if reader returned null") + + // test if fib1 can be written + MITK_TEST_CONDITION_REQUIRED( writer->CanWriteBaseDataType(fib1.GetPointer()),"writer can write data") + writer->SetFileName( std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib" ); + writer->DoWrite( fib1.GetPointer() ); + + // test if fib1 can be read again as fib2 + fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib", s1, s2, false ); + baseData = fibInfile.at(0); + fib2 = dynamic_cast(baseData.GetPointer()); + MITK_TEST_CONDITION_REQUIRED(fib2.IsNotNull(),"reader can read file written before") + + // test if fib1 equals fib2 + MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib2),"fiber bundles are not changed during reading/writing") + } + catch(...) { + //this means that a wrong exception (i.e. no itk:Exception) has been thrown + std::cout << "Wrong exception (i.e. no itk:Exception) caught during write [FAILED]" << std::endl; + return EXIT_FAILURE; + } + + // always end with this! + MITK_TEST_END(); +} diff --git a/Modules/DiffusionImaging/Testing/mitkFiberBundleXTest.cpp b/Modules/DiffusionImaging/Testing/mitkFiberBundleXTest.cpp new file mode 100644 index 0000000000..52ca547666 --- /dev/null +++ b/Modules/DiffusionImaging/Testing/mitkFiberBundleXTest.cpp @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/**Documentation + * Test for fiber bundle reader and writer + */ +int mitkFiberBundleXTest(int argc, char* argv[]) +{ + MITK_TEST_BEGIN("mitkFiberBundleXTest"); + + MITK_TEST_CONDITION_REQUIRED(argc>1,"check for fielename") + + mitk::FiberBundleXReader::Pointer reader = mitk::FiberBundleXReader::New(); + mitk::FiberBundleX::Pointer fib1, fib2; + + // first test: did this work? + // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since + // it makes no sense to continue without an object. + MITK_TEST_CONDITION_REQUIRED(reader.IsNotNull(),"reader instantiation") + + try{ + RegisterDiffusionImagingObjectFactory(); + + // test if fib1 can be read + const std::string s1="", s2=""; + std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[1], s1, s2, false ); + mitk::BaseData::Pointer baseData = fibInfile.at(0); + fib1 = dynamic_cast(baseData.GetPointer()); + MITK_TEST_CONDITION_REQUIRED(fib1.IsNotNull(),"check if reader 1 returned null") + + fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[1], s1, s2, false ); + baseData = fibInfile.at(0); + fib2 = dynamic_cast(baseData.GetPointer()); + MITK_TEST_CONDITION_REQUIRED(fib2.IsNotNull(),"check if reader 2 returned null") + + MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib2),"check if equals method is working"); + + int randNum = rand()%20; + MITK_INFO << "DoFiberSmoothing " << randNum; fib2->DoFiberSmoothing(randNum); + MITK_TEST_CONDITION_REQUIRED(!fib1->Equals(fib2),"check if fiber resampling method does something"); + + mitk::FiberBundleX::Pointer fib3 = fib1->AddBundle(fib2); + MITK_TEST_CONDITION_REQUIRED(!fib1->Equals(fib3),"check if A+B!=A"); + fib3 = fib3->SubtractBundle(fib2); + MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib3),"check if A+B-B==A"); + + fib1->AddBundle(NULL); + MITK_INFO << "GenerateFiberIds"; fib1->GenerateFiberIds(); + MITK_INFO << "GetFiberPolyData"; fib1->GetFiberPolyData(); + MITK_INFO << "GetAvailableColorCodings"; fib1->GetAvailableColorCodings(); + MITK_INFO << "GetCurrentColorCoding"; fib1->GetCurrentColorCoding(); + MITK_INFO << "SetFiberPolyData"; fib1->SetFiberPolyData(NULL); + MITK_INFO << "ExtractFiberSubset"; fib1->ExtractFiberSubset(NULL); + MITK_INFO << "ExtractFiberIdSubset"; fib1->ExtractFiberIdSubset(NULL); + std::vector< long > tmp; + MITK_INFO << "GeneratePolyDataByIds"; fib1->GeneratePolyDataByIds(tmp); + MITK_INFO << "SetColorCoding"; fib1->SetColorCoding(NULL); + MITK_INFO << "SetFAMap"; fib1->SetFAMap(NULL); + MITK_INFO << "DoColorCodingOrientationBased"; fib1->DoColorCodingOrientationBased(); + MITK_INFO << "DoColorCodingFaBased"; fib1->DoColorCodingFaBased(); + MITK_INFO << "DoUseFaFiberOpacity"; fib1->DoUseFaFiberOpacity(); + MITK_INFO << "ResetFiberOpacity"; fib1->ResetFiberOpacity(); + } + catch(...) + { + //this means that a wrong exception (i.e. no itk:Exception) has been thrown + std::cout << "Wrong exception (i.e. no itk:Exception) caught during write [FAILED]" << std::endl; + return EXIT_FAILURE; + } + + // always end with this! + MITK_TEST_END(); +} diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp index 0907ef1cbc..04e8638711 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp @@ -1,179 +1,194 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _BUILDFIBRES #define _BUILDFIBRES //#include "matrix.h" #define _USE_MATH_DEFINES #include #include #include #include using namespace std; #define PI M_PI #include "ParticleGrid.cpp" #include #include #include #include #include #include #include #include class FiberBuilder { public: Particle *particles; int pcnt; int attrcnt; typedef vector< Particle* > ParticleContainerType; typedef vector< ParticleContainerType* > FiberContainerType; vtkSmartPointer m_VtkCellArray; vtkSmartPointer m_VtkPoints; typedef itk::Vector OdfVectorType; typedef itk::Image ItkQBallImgType; ItkQBallImgType::Pointer m_ItkQBallImage; float m_FiberLength; itk::Point m_LastPoint; FiberBuilder(float *points, int numPoints, double spacing[], ItkQBallImgType::Pointer image) { m_FiberLength = 0; m_ItkQBallImage = image; particles = (Particle*) malloc(sizeof(Particle)*numPoints); pcnt = numPoints; attrcnt = 10; for (int k = 0; k < numPoints; k++) { Particle *p = &(particles[k]); p->R = pVector(points[attrcnt*k]/spacing[0]-0.5, points[attrcnt*k+1]/spacing[1]-0.5,points[attrcnt*k+2]/spacing[2]-0.5); p->N = pVector(points[attrcnt*k+3],points[attrcnt*k+4],points[attrcnt*k+5]); p->cap = points[attrcnt*k+6]; p->len = points[attrcnt*k+7]; p->mID = (int) points[attrcnt*k+8]; p->pID = (int) points[attrcnt*k+9]; p->ID = k; p->label = 0; } m_VtkCellArray = vtkSmartPointer::New(); m_VtkPoints = vtkSmartPointer::New(); } ~FiberBuilder() { free(particles); } vtkSmartPointer iterate(int minFiberLength) { int cur_label = 1; int numFibers = 0; m_FiberLength = 0; for (int k = 0; k < pcnt;k++) { Particle *dp = &(particles[k]); if (dp->label == 0) { vtkSmartPointer container = vtkSmartPointer::New(); dp->label = cur_label; dp->numerator = 0; labelPredecessors(dp, container); labelSuccessors(dp, container); cur_label++; if(m_FiberLength >= minFiberLength) { m_VtkCellArray->InsertNextCell(container); numFibers++; } m_FiberLength = 0; } } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(m_VtkPoints); fiberPolyData->SetLines(m_VtkCellArray); // vtkSmartPointer cleaner = vtkSmartPointer::New(); // cleaner->SetInput(fiberPolyData); // cleaner->Update(); // fiberPolyData = cleaner->GetOutput(); return fiberPolyData; } void AddPoint(Particle *dp, vtkSmartPointer container) { if (dp->inserted) return; dp->inserted = true; itk::ContinuousIndex index; index[0] = dp->R[0]; index[1] = dp->R[1]; index[2] = dp->R[2]; itk::Point point; m_ItkQBallImage->TransformContinuousIndexToPhysicalPoint( index, point ); vtkIdType id = m_VtkPoints->InsertNextPoint(point.GetDataPointer()); container->GetPointIds()->InsertNextId(id); if(container->GetNumberOfPoints()>1) m_FiberLength += m_LastPoint.EuclideanDistanceTo(point); m_LastPoint = point; } void labelPredecessors(Particle *dp, vtkSmartPointer container) { if (dp->mID != -1 && dp->mID!=dp->ID) { if (dp->ID!=particles[dp->mID].pID) { if (dp->ID==particles[dp->mID].mID) { int tmp = particles[dp->mID].pID; particles[dp->mID].pID = particles[dp->mID].mID; particles[dp->mID].mID = tmp; } } if (particles[dp->mID].label == 0) { particles[dp->mID].label = dp->label; particles[dp->mID].numerator = dp->numerator-1; labelPredecessors(&(particles[dp->mID]), container); } } AddPoint(dp, container); } void labelSuccessors(Particle *dp, vtkSmartPointer container) { AddPoint(dp, container); if (dp->pID != -1 && dp->pID!=dp->ID) { if (dp->ID!=particles[dp->pID].mID) { if (dp->ID==particles[dp->pID].pID) { int tmp = particles[dp->pID].pID; particles[dp->pID].pID = particles[dp->pID].mID; particles[dp->pID].mID = tmp; } } if (particles[dp->pID].label == 0) { particles[dp->pID].label = dp->label; particles[dp->pID].numerator = dp->numerator+1; labelSuccessors(&(particles[dp->pID]), container); } } } }; #endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp index 3b2d58cf82..b21e77ce88 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp @@ -1,369 +1,384 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _ENCOMPINTERFACE #define _ENCOMPINTERFACE #include "SphereInterpolator.cpp" #include "ParticleGrid.cpp" #include #include #include inline float myATAN2(float y,float x) { float phi = acos(x); // float phi = ((x>=1.0) ? ((0.0000*x+-0.0000)) : ((x>=1.0) ? ((-10.0167*x+10.0167)) : ((x>=0.9) ? ((-3.1336*x+3.2713)) : ((x>=0.8) ? ((-1.9247*x+2.1833)) : ((x>=0.5) ? ((-1.3457*x+1.7200)) : ((x>=0.0) ? ((-1.0472*x+1.5708)) : ((x>=-0.5) ? ((-1.0472*x+1.5708)) : ((x>=-0.8) ? ((-1.3457*x+1.4216)) : ((x>=-0.9) ? ((-1.9247*x+0.9583)) : ((x>=-1.0) ? ((-3.1336*x+-0.1297)) : ((x>=-1.0) ? ((-10.0167*x+-6.8751)) : 1 ))))))))))); if (y < 0) phi = 2*PI - phi; if (phi<0) phi = phi + PI; return phi; } class EnergyComputerBase { public: float *m_QBallImageData; const int *m_QBallImageSize; SphereInterpolator *m_SphereInterpolator; ParticleGrid *m_ParticleGrid; int w,h,d; float voxsize_w; float voxsize_h; float voxsize_d; int w_sp,h_sp,d_sp; float voxsize_sp_w; float voxsize_sp_h; float voxsize_sp_d; int nip; // number of data vertices on sphere float *m_MaskImageData; float *cumulspatprob; int *spatidx; int scnt; float eigen_energy; vnl_matrix_fixed m_RotationMatrix; EnergyComputerBase(float *qBallImageData, const int *qBallImageSize, double *voxsize, SphereInterpolator *sp, ParticleGrid *pcon, float *maskImageData, int spmult, vnl_matrix_fixed rotMatrix) { m_RotationMatrix = rotMatrix; m_QBallImageData = qBallImageData; m_QBallImageSize = qBallImageSize; m_SphereInterpolator = sp; m_MaskImageData = maskImageData; nip = m_QBallImageSize[0]; w = m_QBallImageSize[1]; h = m_QBallImageSize[2]; d = m_QBallImageSize[3]; voxsize_w = voxsize[0]; voxsize_h = voxsize[1]; voxsize_d = voxsize[2]; w_sp = m_QBallImageSize[1]*spmult; h_sp = m_QBallImageSize[2]*spmult; d_sp = m_QBallImageSize[3]*spmult; voxsize_sp_w = voxsize[0]/spmult; voxsize_sp_h = voxsize[1]/spmult; voxsize_sp_d = voxsize[2]/spmult; fprintf(stderr,"Data size (voxels) : %i x %i x %i\n",w,h,d); fprintf(stderr,"voxel size: %f x %f x %f\n",voxsize_w,voxsize_h,voxsize_d); fprintf(stderr,"mask_oversamp_mult: %i\n",spmult); if (nip != sp->nverts) { fprintf(stderr,"EnergyComputer: error during init: data does not match with interpolation scheme\n"); } m_ParticleGrid = pcon; int totsz = w_sp*h_sp*d_sp; cumulspatprob = (float*) malloc(sizeof(float) * totsz); spatidx = (int*) malloc(sizeof(int) * totsz); if (cumulspatprob == 0 || spatidx == 0) { fprintf(stderr,"EnergyCOmputerBase: out of memory!\n"); return ; } scnt = 0; cumulspatprob[0] = 0; for (int x = 1; x < w_sp;x++) for (int y = 1; y < h_sp;y++) for (int z = 1; z < d_sp;z++) { int idx = x+(y+z*h_sp)*w_sp; if (m_MaskImageData[idx] > 0.5) { cumulspatprob[scnt+1] = cumulspatprob[scnt] + m_MaskImageData[idx]; spatidx[scnt] = idx; scnt++; } } for (int k = 0; k < scnt; k++) { cumulspatprob[k] /= cumulspatprob[scnt]; } fprintf(stderr,"#active voxels: %i (in mask units) \n",scnt); } ~EnergyComputerBase() { free(cumulspatprob); free(spatidx); } virtual void setParameters() { } void drawSpatPosition(pVector *R) { float r = mtrand.frand(); int j; int rl = 1; int rh = scnt; while(rh != rl) { j = rl + (rh-rl)/2; if (r < cumulspatprob[j]) { rh = j; continue; } if (r > cumulspatprob[j]) { rl = j+1; continue; } break; } R->SetXYZ(voxsize_sp_w*((float)(spatidx[rh-1] % w_sp) + mtrand.frand()), voxsize_sp_h*((float)((spatidx[rh-1]/w_sp) % h_sp) + mtrand.frand()), voxsize_sp_d*((float)(spatidx[rh-1]/(w_sp*h_sp)) + mtrand.frand())); } float SpatProb(pVector R) { int rx = int(R.GetX()/voxsize_sp_w); int ry = int(R.GetY()/voxsize_sp_h); int rz = int(R.GetZ()/voxsize_sp_d); if (rx >= 0 && rx < w_sp && ry >= 0 && ry < h_sp && rz >= 0 && rz < d_sp){ return m_MaskImageData[rx + w_sp* (ry + h_sp*rz)]; } else return 0; } /* inline float evaluateODF(pVector &R, pVector &N, float &len) { const int CU = 10; pVector Rs; float Dn = 0; int xint,yint,zint,spatindex; sinterp->getInterpolation(N); for (int i=-CU; i < CU;i++) { Rs = R + (N * len) * ((float)i/CU); xint = int(Rs.x); yint = int(Rs.y); zint = int(Rs.z); if (xint > 0 && xint < w-1 && yint > 0 && yint < h-1 && zint > 0 && zint < d-1) { spatindex = (xint + w*(yint+h*zint)) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2]); } } Dn /= (float)(2*CU+1); return Dn; } */ inline float evaluateODF(pVector &R, pVector &N, float &len) { const int CU = 10; pVector Rs; float Dn = 0; int xint,yint,zint,spatindex; vnl_vector_fixed n; n[0] = N[0]; n[1] = N[1]; n[2] = N[2]; n = m_RotationMatrix*n; m_SphereInterpolator->getInterpolation(n); for (int i=-CU; i <= CU;i++) { Rs = R + (N * len) * ((float)i/CU); float Rx = Rs[0]/voxsize_w-0.5; float Ry = Rs[1]/voxsize_h-0.5; float Rz = Rs[2]/voxsize_d-0.5; xint = int(floor(Rx)); yint = int(floor(Ry)); zint = int(floor(Rz)); if (xint >= 0 && xint < w-1 && yint >= 0 && yint < h-1 && zint >= 0 && zint < d-1) { float xfrac = Rx-xint; float yfrac = Ry-yint; float zfrac = Rz-zint; float weight; weight = (1-xfrac)*(1-yfrac)*(1-zfrac); spatindex = (xint + w*(yint+h*zint)) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (xfrac)*(1-yfrac)*(1-zfrac); spatindex = (xint+1 + w*(yint+h*zint)) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (1-xfrac)*(yfrac)*(1-zfrac); spatindex = (xint + w*(yint+1+h*zint)) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (1-xfrac)*(1-yfrac)*(zfrac); spatindex = (xint + w*(yint+h*(zint+1))) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (xfrac)*(yfrac)*(1-zfrac); spatindex = (xint+1 + w*(yint+1+h*zint)) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (1-xfrac)*(yfrac)*(zfrac); spatindex = (xint + w*(yint+1+h*(zint+1))) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (xfrac)*(1-yfrac)*(zfrac); spatindex = (xint+1 + w*(yint+h*(zint+1))) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; weight = (xfrac)*(yfrac)*(zfrac); spatindex = (xint+1 + w*(yint+1+h*(zint+1))) *nip; Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; } } Dn *= 1.0/(2*CU+1); return Dn; } /* inline float evaluateODF(pVector &R, pVector &N, float &len) { R.storeXYZ(); float Rx = pVector::store[0]/voxsize_w; float Ry = pVector::store[1]/voxsize_h; float Rz = pVector::store[2]/voxsize_d; int xint = int(Rx); int yint = int(Ry); int zint = int(Rz); if (xint >= 0 && xint < w-1 && yint >= 0 && yint < h-1 && zint >= 0 && zint < d-1) { float xfrac = Rx-xint; float yfrac = Ry-yint; float zfrac = Rz-zint; sinterp->getInterpolation(N); float weight; int spatindex; float Dn = 0; weight = (1-xfrac)*(1-yfrac)*(1-zfrac); spatindex = (xint + w*(yint+h*zint)) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (xfrac)*(1-yfrac)*(1-zfrac); spatindex = (xint+1 + w*(yint+h*zint)) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (1-xfrac)*(yfrac)*(1-zfrac); spatindex = (xint + w*(yint+1+h*zint)) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (1-xfrac)*(1-yfrac)*(zfrac); spatindex = (xint + w*(yint+h*(zint+1))) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (xfrac)*(yfrac)*(1-zfrac); spatindex = (xint+1 + w*(yint+1+h*zint)) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (1-xfrac)*(yfrac)*(zfrac); spatindex = (xint + w*(yint+1+h*(zint+1))) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (xfrac)*(1-yfrac)*(zfrac); spatindex = (xint+1 + w*(yint+h*(zint+1))) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; weight = (xfrac)*(yfrac)*(zfrac); spatindex = (xint+1 + w*(yint+1+h*(zint+1))) *nip; Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; return Dn; } return 0; } */ virtual inline float computeExternalEnergy(pVector &R, pVector &N, float &cap, float &len, Particle *dp) { return 0;} virtual inline float computeInternalEnergy(Particle *p1) {return 0;} virtual inline float computeInternalEnergyConnection(Particle *p1,int ep1) {return 0;} virtual inline float computeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) {return 0;} }; #endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp index ba20e4be5b..ec23b23b27 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp @@ -1,222 +1,237 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /// bessel for wid = 1 //#define mbesseli0(x) ((x>=1.0) ? ((-0.2578*x+0.7236)*exp(x)) : ((x>=0.9) ? ((-0.2740*x+0.7398)*exp(x)) : ((x>=0.8) ? ((-0.3099*x+0.7720)*exp(x)) : ((x>=0.7) ? ((-0.3634*x+0.8149)*exp(x)) : ((x>=0.5) ? ((-0.4425*x+0.8663)*exp(x)) : ((x>=0.3) ? ((-0.5627*x+0.9264)*exp(x)) : ((x>=0.2) ? ((-0.6936*x+0.9657)*exp(x)) : ((x>=0.1) ? ((-0.8016*x+0.9873)*exp(x)) : ((x>=0.0) ? ((-0.9290*x+1.0000)*exp(x)) : 1 ))))))))) //#define mbesseli0(x) ((x>=1.0) ? ((0.5652*x+0.7009)) : ((x>=0.8) ? ((0.4978*x+0.7683)) : ((x>=0.6) ? ((0.3723*x+0.8686)) : ((x>=0.4) ? ((0.2582*x+0.9371)) : ((x>=0.2) ? ((0.1519*x+0.9796)) : ((x>=0.0) ? ((0.0501*x+1.0000)) : 1 )))))) inline float mbesseli0(float x) { float y = x*x; float erg = BESSEL_APPROXCOEFF[0]; erg += y*BESSEL_APPROXCOEFF[1]; erg += y*y*BESSEL_APPROXCOEFF[2]; erg += y*y*y*BESSEL_APPROXCOEFF[3]; return erg; } // // // inline REAL mbesseli0(REAL x) // { // REAL y = x*x; // REAL erg = BESSEL_APPROXCOEFF[0]; // erg += y*BESSEL_APPROXCOEFF[1]; // erg += y*x*BESSEL_APPROXCOEFF[2]; // erg += x*x*BESSEL_APPROXCOEFF[3]; // return erg; // } inline float mexp(float x) { return((x>=7.0) ? 0 : ((x>=5.0) ? (-0.0029*x+0.0213) : ((x>=3.0) ? (-0.0215*x+0.1144) : ((x>=2.0) ? (-0.0855*x+0.3064) : ((x>=1.0) ? (-0.2325*x+0.6004) : ((x>=0.5) ? (-0.4773*x+0.8452) : ((x>=0.0) ? (-0.7869*x+1.0000) : 1 ))))))); // return exp(-x); } #include "ParticleGrid.cpp" #include "EnergyComputerBase.cpp" #include class EnergyComputer : public EnergyComputerBase { public: float eigencon_energy; float chempot2; float meanval_sq; float gamma_s; float gamma_reg_s; float particle_weight; float ex_strength; float in_strength; float particle_length_sq; float curv_hard; EnergyComputer(float *data, const int *dsz, double *cellsize, SphereInterpolator *sp, ParticleGrid *pcon, float *spimg, int spmult, vnl_matrix_fixed rotMatrix) : EnergyComputerBase(data,dsz,cellsize,sp,pcon,spimg,spmult,rotMatrix) { } void setParameters(float pwei,float pwid,float chempot_connection, float length,float curv_hardthres, float inex_balance, float chempot2, float meanv) { this->chempot2 = chempot2; meanval_sq = meanv; eigencon_energy = chempot_connection; eigen_energy = 0; particle_weight = pwei; float bal = 1/(1+exp(-inex_balance)); ex_strength = 2*bal; // cleanup (todo) in_strength = 2*(1-bal)/length/length; // cleanup (todo) // in_strength = 0.64/length/length; // cleanup (todo) particle_length_sq = length*length; curv_hard = curv_hardthres; float sigma_s = pwid; gamma_s = 1/(sigma_s*sigma_s); gamma_reg_s =1/(length*length/4); } //////////////////////////////////////////////////////////////////////////// ////// External Energy //////////////////////////////////////////////////////////////////////////// inline float computeExternalEnergy(pVector &R, pVector &N, float &cap, float &len, Particle *dp) { float m = SpatProb(R); if (m == 0) { return -INFINITY; } float Dn = evaluateODF(R,N,len); float Sn = 0; float Pn = 0; m_ParticleGrid->computeNeighbors(R); for (;;) { Particle *p = m_ParticleGrid->getNextNeighbor(); if (p == 0) break; if (dp != p) { float dot = fabs(N*p->N); float bw = mbesseli0(dot); float dpos = (p->R-R).norm_square(); float w = mexp(dpos*gamma_s); Sn += w*(bw+chempot2)*p->cap ; //Sn += w*(bw-meanval_sq)*p->cap ; w = mexp(dpos*gamma_reg_s); Pn += w*bw; } } float energy = 0; energy += (2*(Dn/particle_weight-Sn) - (mbesseli0(1.0)+chempot2)*cap)*cap; //energy += (2*(Dn/particle_weight-Sn) - (mbesseli0(1.0)-meanval_sq)*cap)*cap; return energy*ex_strength; } //////////////////////////////////////////////////////////////////////////// ////// Internal Energy //////////////////////////////////////////////////////////////////////////// inline float computeInternalEnergy(Particle *dp) { float energy = eigen_energy; if (dp->pID != -1) energy += computeInternalEnergyConnection(dp,+1); if (dp->mID != -1) energy += computeInternalEnergyConnection(dp,-1); //ie_file << energy << "\n"; return energy; } inline float computeInternalEnergyConnection(Particle *p1,int ep1) { Particle *p2 = 0; int ep2; if (ep1 == 1) p2 = m_ParticleGrid->ID_2_address[p1->pID]; else p2 = m_ParticleGrid->ID_2_address[p1->mID]; if (p2->mID == p1->ID) ep2 = -1; else if (p2->pID == p1->ID) ep2 = 1; else fprintf(stderr,"EnergyComputer_connec: Connections are inconsistent!\n"); if (p2 == 0) fprintf(stderr,"bug2"); return computeInternalEnergyConnection(p1,ep1,p2,ep2); } inline float computeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) { #ifdef TIMING tic(&internalenergy_time); #endif if ((p1->N*p2->N)*ep1*ep2 > -curv_hard) return -INFINITY; pVector R1 = p1->R + (p1->N * (p1->len * ep1)); pVector R2 = p2->R + (p2->N * (p2->len * ep2)); if ((R1-R2).norm_square() > particle_length_sq) return -INFINITY; pVector R = (p2->R + p1->R)*0.5; if (SpatProb(R) == 0) return -INFINITY; float norm1 = (R1-R).norm_square(); float norm2 = (R2-R).norm_square(); float energy = (eigencon_energy-norm1-norm2)*in_strength; #ifdef TIMING toc(&internalenergy_time); #endif return energy; } }; diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h index 474a32fdb5..01d0784e24 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h @@ -1,596 +1,611 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ // MersenneTwister.h // Mersenne Twister random number generator -- a C++ class MTRand // Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus // Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com // The Mersenne Twister is an algorithm for generating random numbers. It // was designed with consideration of the flaws in various other generators. // The period, 2^19937-1, and the order of equidistribution, 623 dimensions, // are far greater. The generator is also fast; it avoids multiplication and // division, and it benefits from caches and pipelines. For more information // see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html // Reference // M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally // Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on // Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, // Copyright (C) 2000 - 2003, Richard J. Wagner // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The names of its contributors may not be used to endorse or promote // products derived from this software without specific prior written // permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // The original code included the following notice: // // When you use this, send an email to: matumoto@math.keio.ac.jp // with an appropriate reference to your work. // // It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu // when you write. #ifndef MERSENNETWISTER_H #define MERSENNETWISTER_H // Not thread safe (unless auto-initialization is avoided and each thread has // its own MTRand object) #include #include #include #include #define _USE_MATH_DEFINES #include class MTRand { // Data public: typedef unsigned long uint32; // unsigned integer type, at least 32 bits enum { N = 624 }; // length of state vector enum { SAVE = N + 1 }; // length of array for save() // protected: enum { M = 397 }; // period parameter uint32 state[N]; // internal state uint32 *pNext; // next value to get from state int left; // number of values left before reload needed //Methods public: MTRand( const uint32& oneSeed ); // initialize with a simple uint32 MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array MTRand(); // auto-initialize with /dev/urandom or time() and clock() ~MTRand(); // Do NOT use for CRYPTOGRAPHY without securely hashing several returned // values together, otherwise the generator state can be learned after // reading 624 consecutive values. // Access to 32-bit random numbers double rand(); // real number in [0,1] float frand(); // real number in [0,1] double rand( const double& n ); // real number in [0,n] double randExc(); // real number in [0,1) double randExc( const double& n ); // real number in [0,n) double randDblExc(); // real number in (0,1) double randDblExc( const double& n ); // real number in (0,n) uint32 randInt(); // integer in [0,2^32-1] uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32 double operator()() { return rand(); } // same as rand() // Access to 53-bit random numbers (capacity of IEEE double precision) double rand53(); // real number in [0,1) // Access to nonuniform random number distributions double randNorm( const double& mean = 0.0, const double& variance = 0.0 ); float frandn(); // Re-seeding functions with same behavior as initializers void seed( const uint32 oneSeed ); void seed( uint32 *const bigSeed, const uint32 seedLength = N ); void seed(); ////// int Poisson(); void initPoisson(float mean, int accuracy); float *cumulPoisson; int accuracyPoisson; int drawGamma(); void initGamma(float theta, int shape); float *cumulGamma; int accuracyGamma; // Saving and loading generator state void save( uint32* saveArray ) const; // to array of size SAVE void load( uint32 *const loadArray ); // from such array friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ); friend std::istream& operator>>( std::istream& is, MTRand& mtrand ); protected: void initialize( const uint32 oneSeed ); void reload(); uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; } uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; } uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; } uint32 mixBits( const uint32& u, const uint32& v ) const { return hiBit(u) | loBits(v); } uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); } static uint32 hash( time_t t, clock_t c ); }; inline MTRand::MTRand( const uint32& oneSeed ) { seed(oneSeed); cumulPoisson = 0; cumulGamma = 0; } inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength ) { seed(bigSeed,seedLength); cumulPoisson = 0; cumulGamma = 0; } inline MTRand::MTRand() { seed(); cumulPoisson = 0; cumulGamma = 0; } inline MTRand::~MTRand() { if (cumulPoisson != 0) free(cumulPoisson); if (cumulGamma != 0) free(cumulGamma); } inline double MTRand::rand() { return double(randInt()) * (1.0/4294967295.0); } inline float MTRand::frand() { return float(randInt()) * (1.0/4294967295.0); } inline double MTRand::rand( const double& n ) { return rand() * n; } inline double MTRand::randExc() { return double(randInt()) * (1.0/4294967296.0); } inline double MTRand::randExc( const double& n ) { return randExc() * n; } inline double MTRand::randDblExc() { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } inline double MTRand::randDblExc( const double& n ) { return randDblExc() * n; } inline double MTRand::rand53() { uint32 a = randInt() >> 5, b = randInt() >> 6; return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada } inline double MTRand::randNorm( const double& mean, const double& variance ) { // Return a real number from a normal (Gaussian) distribution with given // mean and variance by Box-Muller method double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance; double phi = 2.0 * M_PI * randExc(); return mean + r * cos(phi); } inline float MTRand::frandn() { // Return a real number from a normal (Gaussian) distribution with given // mean and variance by Box-Muller method float r = sqrt( -2.0 * log( 1.0-randDblExc()) ); double phi = 2.0 * M_PI * randExc(); return r * cos(phi); } inline int MTRand::Poisson() { int j; float r = frand(); int rl = 0; int rh = accuracyPoisson-1; while(rh != rl) { j = rl + (rh-rl)/2; if (r < cumulPoisson[j]) { rh = j; continue; } if (r > cumulPoisson[j]) { rl = j+1; continue; } break; } j = rh; return j; } inline int MTRand::drawGamma() { int j; float r = frand(); int rl = 0; int rh = accuracyGamma-1; while(rh != rl) { j = rl + (rh-rl)/2; if (r < cumulGamma[j]) { rh = j; continue; } if (r > cumulGamma[j]) { rl = j+1; continue; } break; } j = rh; return j; } /* inline void MTRand::initPoisson(float mean,int accuracy) { float p[accuracy]; float Z = exp(-mean); p[0] = 1; for (int i = 1; i < accuracy;i++) p[i] = p[i-1]*mean/i; for (int i = 0; i < accuracy;i++) p[i] *= Z; if (cumulPoisson != 0) free(cumulPoisson); cumulPoisson = (float*) malloc(sizeof(float)*accuracy); cumulPoisson[0] = p[0]; for (int i = 1; i < accuracy;i++) cumulPoisson[i] = cumulPoisson[i-1]+p[i]; for (int i = 0; i < accuracy;i++) cumulPoisson[i] = cumulPoisson[i]/cumulPoisson[accuracy-1]; accuracyPoisson = accuracy; } inline void MTRand::initGamma(float theta,int k) { int accuracy = int(k*theta*5); float p[accuracy]; int fac = 1; for (int i = 1; i < k-1;i++) fac *= i; for (int i = 0; i < accuracy;i++) { p[i] = pow(i/theta,k-1)/fac * exp(i/theta); } if (cumulGamma != 0) free(cumulGamma); cumulGamma = (float*) malloc(sizeof(float)*accuracy); cumulGamma[0] = p[0]; for (int i = 1; i < accuracy;i++) cumulGamma[i] = cumulGamma[i-1]+p[i]; for (int i = 0; i < accuracy;i++) cumulGamma[i] = cumulGamma[i]/cumulGamma[accuracy-1]; accuracyGamma = accuracy; } */ inline MTRand::uint32 MTRand::randInt() { // Pull a 32-bit integer from the generator state // Every other access function simply transforms the numbers extracted here if( left == 0 ) reload(); --left; register uint32 s1; s1 = *pNext++; s1 ^= (s1 >> 11); s1 ^= (s1 << 7) & 0x9d2c5680UL; s1 ^= (s1 << 15) & 0xefc60000UL; return ( s1 ^ (s1 >> 18) ); } inline MTRand::uint32 MTRand::randInt( const uint32& n ) { // Find which bits are used in n // Optimized by Magnus Jonsson (magnus@smartelectronix.com) uint32 used = n; used |= used >> 1; used |= used >> 2; used |= used >> 4; used |= used >> 8; used |= used >> 16; // Draw numbers until one is found in [0,n] uint32 i; do i = randInt() & used; // toss unused bits to shorten search while( i > n ); return i; } inline void MTRand::seed( const uint32 oneSeed ) { // Seed the generator with a simple uint32 initialize(oneSeed); reload(); } inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength ) { // Seed the generator with an array of uint32's // There are 2^19937-1 possible initial states. This function allows // all of those to be accessed by providing at least 19937 bits (with a // default seed length of N = 624 uint32's). Any bits above the lower 32 // in each element are discarded. // Just call seed() if you want to get array from /dev/urandom initialize(19650218UL); register int i = 1; register uint32 j = 0; register int k = ( N > seedLength ? N : seedLength ); for( ; k; --k ) { state[i] = state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; state[i] &= 0xffffffffUL; ++i; ++j; if( i >= N ) { state[0] = state[N-1]; i = 1; } if( j >= seedLength ) j = 0; } for( k = N - 1; k; --k ) { state[i] = state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); state[i] -= i; state[i] &= 0xffffffffUL; ++i; if( i >= N ) { state[0] = state[N-1]; i = 1; } } state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array reload(); } inline void MTRand::seed() { // Seed the generator with an array from /dev/urandom if available // Otherwise use a hash of time() and clock() values // First try getting an array from /dev/urandom FILE* urandom = fopen( "/dev/urandom", "rb" ); if( urandom ) { uint32 bigSeed[N]; register uint32 *s = bigSeed; register int i = N; register bool success = true; while( success && i-- ) success = fread( s++, sizeof(uint32), 1, urandom ); fclose(urandom); if( success ) { seed( bigSeed, N ); return; } } // Was not successful, so use time() and clock() instead seed( hash( time(NULL), clock() ) ); } inline void MTRand::initialize( const uint32 seed ) { // Initialize generator state with seed // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. // In previous versions, most significant bits (MSBs) of the seed affect // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. register uint32 *s = state; register uint32 *r = state; register int i = 1; *s++ = seed & 0xffffffffUL; for( ; i < N; ++i ) { *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; r++; } } inline void MTRand::reload() { // Generate N new values in state // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) register uint32 *p = state; register int i; for( i = N - M; i--; ++p ) *p = twist( p[M], p[0], p[1] ); for( i = M; --i; ++p ) *p = twist( p[M-N], p[0], p[1] ); *p = twist( p[M-N], p[0], state[0] ); left = N, pNext = state; } inline MTRand::uint32 MTRand::hash( time_t t, clock_t c ) { // Get a uint32 from t and c // Better than uint32(x) in case x is floating point in [0,1] // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk) static uint32 differ = 0; // guarantee time-based seeds will change uint32 h1 = 0; unsigned char *p = (unsigned char *) &t; for( size_t i = 0; i < sizeof(t); ++i ) { h1 *= UCHAR_MAX + 2U; h1 += p[i]; } uint32 h2 = 0; p = (unsigned char *) &c; for( size_t j = 0; j < sizeof(c); ++j ) { h2 *= UCHAR_MAX + 2U; h2 += p[j]; } return ( h1 + differ++ ) ^ h2; } inline void MTRand::save( uint32* saveArray ) const { register uint32 *sa = saveArray; register const uint32 *s = state; register int i = N; for( ; i--; *sa++ = *s++ ) {} *sa = left; } inline void MTRand::load( uint32 *const loadArray ) { register uint32 *s = state; register uint32 *la = loadArray; register int i = N; for( ; i--; *s++ = *la++ ) {} left = *la; pNext = &state[N-left]; } inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ) { register const MTRand::uint32 *s = mtrand.state; register int i = mtrand.N; for( ; i--; os << *s++ << "\t" ) {} return os << mtrand.left; } inline std::istream& operator>>( std::istream& is, MTRand& mtrand ) { register MTRand::uint32 *s = mtrand.state; register int i = mtrand.N; for( ; i--; is >> *s++ ) {} is >> mtrand.left; mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; return is; } #endif // MERSENNETWISTER_H // Change log: // // v0.1 - First release on 15 May 2000 // - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus // - Translated from C to C++ // - Made completely ANSI compliant // - Designed convenient interface for initialization, seeding, and // obtaining numbers in default or user-defined ranges // - Added automatic seeding from /dev/urandom or time() and clock() // - Provided functions for saving and loading generator state // // v0.2 - Fixed bug which reloaded generator one step too late // // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew // // v0.4 - Removed trailing newline in saved generator format to be consistent // with output format of built-in types // // v0.5 - Improved portability by replacing static const int's with enum's and // clarifying return values in seed(); suggested by Eric Heimburg // - Removed MAXINT constant; use 0xffffffffUL instead // // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits // - Changed integer [0,n] generator to give better uniformity // // v0.7 - Fixed operator precedence ambiguity in reload() // - Added access for real numbers in (0,1) and (0,n) // // v0.8 - Included time.h header to properly support time_t and clock_t // // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto // - Allowed for seeding with arrays of any length // - Added access for real numbers in [0,1) with 53-bit resolution // - Added access for real numbers from normal (Gaussian) distributions // - Increased overall speed by optimizing twist() // - Doubled speed of integer [0,n] generation // - Fixed out-of-range number generation on 64-bit machines // - Improved portability by substituting literal constants for long enum's // - Changed license from GNU LGPL to BSD diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp index 44e32fd473..ab8c49410a 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp @@ -1,610 +1,625 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _PARTICLEGRID #define _PARTICLEGRID #include "auxilary_classes.cpp" template class ParticleGrid { //////////////// Container public: T *particles; // particles in linear array int pcnt; // actual number of particles int concnt; // number of connections int celloverflows; T **ID_2_address; private: int capacity; // maximal number of particles int increase_step; /////////////////// Grid T **grid; // the grid // grid size int nx; int ny; int nz; // scaling factor for grid float mulx; float muly; float mulz; int csize; // particle capacity of single cell in grid int *occnt; // occupation count of grid cells int gridsize; // total number of cells float m_Memory; struct NeighborTracker // to run over the neighbors { int cellidx[8]; int cellidx_c[8]; int cellcnt; int pcnt; } nbtrack; public: ParticleGrid() { //// involving the container capacity = 0; particles = 0; ID_2_address = 0; pcnt = 0; concnt = 0; celloverflows = 0; ////// involvin the grid nx = 0; ny = 0; nz = 0; csize = 0; gridsize = 0; grid = (T**) 0; occnt = (int*) 0; increase_step = 100000; m_Memory = 0; } float GetMemoryUsage() { return m_Memory; } int allocate(int _capacity, int _nx, int _ny, int _nz, float cellsize, int cellcapacity) { //// involving the container capacity = _capacity; particles = (T*) malloc(sizeof(T)*capacity); ID_2_address = (T**) malloc(sizeof(T*)*capacity); if (particles == 0 || ID_2_address == 0) { fprintf(stderr,"error: Out of Memory\n"); capacity = 0; return -1; } else { fprintf(stderr,"Allocated Memory for %i particles \n",capacity); } pcnt = 0; int i; for (i = 0;i < capacity;i++) { ID_2_address[i] = &(particles[i]); // initialize pointer in LUT particles[i].ID = i; // initialize unique IDs } ////// involvin the grid nx = _nx; ny = _ny; nz = _nz; csize = cellcapacity; gridsize = nx*ny*nz; m_Memory = (float)(sizeof(T*)*gridsize*csize)/1000000; grid = (T**) malloc(sizeof(T*)*gridsize*csize); occnt = (int*) malloc(sizeof(int)*gridsize); if (grid == 0 || occnt == 0) { fprintf(stderr,"error: Out of Memory\n"); capacity = 0; return -1; } for (i = 0;i < gridsize;i++) occnt[i] = 0; mulx = 1/cellsize; muly = 1/cellsize; mulz = 1/cellsize; return 1; } int reallocate() { int new_capacity = capacity + increase_step; T* new_particles = (T*) realloc(particles,sizeof(T)*new_capacity); T** new_ID_2_address = (T**) realloc(ID_2_address,sizeof(T*)*new_capacity); if (new_particles == 0 || new_ID_2_address == 0) { fprintf(stderr,"ParticleGird:reallocate: out of memory!\n"); return -1; } fprintf(stderr," now %i particles are allocated \n",new_capacity); m_Memory = (float)(sizeof(T*)*new_capacity)/1000000; int i; for (i = 0; i < capacity; i++) { new_ID_2_address[i] = new_ID_2_address[i] - particles + new_particles; // shift address } for (i = capacity; i < new_capacity; i++) { new_particles[i].ID = i; // initialize unique IDs new_ID_2_address[i] = &(new_particles[i]) ; // initliaze pointer in LUT } for (i = 0; i < nx*ny*nz*csize; i++) { grid[i] = grid[i] - particles + new_particles; } particles = new_particles; ID_2_address = new_ID_2_address; capacity = new_capacity; return 1; } ~ParticleGrid() { if (particles != 0) free(particles); if (grid != 0) free(grid); if (occnt != 0) free(occnt); if (ID_2_address != 0) free(ID_2_address); } int ID_2_index(int ID) { if (ID == -1) return -1; else return (ID_2_address[ID] - particles); } T* newParticle(pVector R) { /////// get free place in container; if (pcnt >= capacity) { fprintf(stderr,"capacity overflow , reallocating ...\n"); if (reallocate() == -1) { fprintf(stderr,"out of Memory!!\n"); return 0; } } int xint = int(R[0]*mulx); if (xint < 0) { //fprintf(stderr,"error: out of grid\n"); return 0;} if (xint >= nx) { // fprintf(stderr,"error: out of grid\n"); return 0;} int yint = int(R[1]*muly); if (yint < 0) { //fprintf(stderr,"error: out of grid\n"); return 0;} if (yint >= ny) {// fprintf(stderr,"error: out of grid\n"); return 0;} int zint = int(R[2]*mulz); if (zint < 0) {// fprintf(stderr,"error: out of grid\n"); return 0;} if (zint >= nz) { //fprintf(stderr,"error: out of grid\n"); return 0;} int idx = xint + nx*(yint + ny*zint); if (occnt[idx] < csize) { T *p = &(particles[pcnt]); p->R = R; p->mID = -1; p->pID = -1; pcnt++; p->gridindex = csize*idx + occnt[idx]; grid[p->gridindex] = p; occnt[idx]++; return p; } else { celloverflows++; //fprintf(stderr,"error: cell overflow \n"); return 0; } } inline void updateGrid(int k) { T* p = &(particles[k]); /////// find new grid cell int xint = int(p->R[0]*mulx); if (xint < 0) { remove(k); return; } if (xint >= nx) { remove(k); return; } int yint = int(p->R[1]*muly); if (yint < 0) { remove(k); return; } if (yint >= ny) { remove(k); return; } int zint = int(p->R[2]*mulz); if (zint < 0) { remove(k); return; } if (zint >= nz) { remove(k); return; } int idx = xint + nx*(yint+ zint*ny); int cellidx = p->gridindex/csize; if (idx != cellidx) // cell has changed { if (occnt[idx] < csize) { // remove from old position in grid; int grdindex = p->gridindex; grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; grid[grdindex]->gridindex = grdindex; occnt[cellidx]--; // insert at new position in grid p->gridindex = idx*csize + occnt[idx]; grid[p->gridindex] = p; occnt[idx]++; } else remove(k); } } inline bool tryUpdateGrid(int k) { T* p = &(particles[k]); /////// find new grid cell int xint = int(p->R[0]*mulx); if (xint < 0) { return false; } if (xint >= nx) { return false; } int yint = int(p->R[1]*muly); if (yint < 0) { return false; } if (yint >= ny) { return false; } int zint = int(p->R[2]*mulz); if (zint < 0) { return false; } if (zint >= nz) { return false; } int idx = xint + nx*(yint+ zint*ny); int cellidx = p->gridindex/csize; if (idx != cellidx) // cell has changed { if (occnt[idx] < csize) { // remove from old position in grid; int grdindex = p->gridindex; grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; grid[grdindex]->gridindex = grdindex; occnt[cellidx]--; // insert at new position in grid p->gridindex = idx*csize + occnt[idx]; grid[p->gridindex] = p; occnt[idx]++; return true; } else return false; } return true; } inline void remove(int k) { T* p = &(particles[k]); int grdindex = p->gridindex; int cellidx = grdindex/csize; int idx = grdindex%csize; // remove pending connections if (p->mID != -1) destroyConnection(p,-1); if (p->pID != -1) destroyConnection(p,+1); // remove from grid if (idx < occnt[cellidx]-1) { grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; grid[grdindex]->gridindex = grdindex; } occnt[cellidx]--; // remove from container if (kID; int move_ID = particles[pcnt-1].ID; *p = particles[pcnt-1]; // move very last particle to empty slot particles[pcnt-1].ID = todel_ID; // keep IDs unique grid[p->gridindex] = p; // keep gridindex consistent // permute address table ID_2_address[todel_ID] = &(particles[pcnt-1]); ID_2_address[move_ID] = p; } pcnt--; } inline void computeNeighbors(pVector &R) { float xfrac = R.GetX()*mulx; float yfrac = R.GetY()*muly; float zfrac = R.GetZ()*mulz; int xint = int(xfrac); int yint = int(yfrac); int zint = int(zfrac); int dx = -1; if (xfrac-xint > 0.5) dx = 1; if (xint <= 0) { xint = 0; dx = 1; } if (xint >= nx-1) { xint = nx-1; dx = -1; } int dy = -1; if (yfrac-yint > 0.5) dy = 1; if (yint <= 0) {yint = 0; dy = 1; } if (yint >= ny-1) {yint = ny-1; dy = -1;} int dz = -1; if (zfrac-zint > 0.5) dz = 1; if (zint <= 0) {zint = 0; dz = 1; } if (zint >= nz-1) {zint = nz-1; dz = -1;} nbtrack.cellidx[0] = xint + nx*(yint+zint*ny); nbtrack.cellidx[1] = nbtrack.cellidx[0] + dx; nbtrack.cellidx[2] = nbtrack.cellidx[1] + dy*nx; nbtrack.cellidx[3] = nbtrack.cellidx[2] - dx; nbtrack.cellidx[4] = nbtrack.cellidx[0] + dz*nx*ny; nbtrack.cellidx[5] = nbtrack.cellidx[4] + dx; nbtrack.cellidx[6] = nbtrack.cellidx[5] + dy*nx; nbtrack.cellidx[7] = nbtrack.cellidx[6] - dx; nbtrack.cellidx_c[0] = csize*nbtrack.cellidx[0]; nbtrack.cellidx_c[1] = csize*nbtrack.cellidx[1]; nbtrack.cellidx_c[2] = csize*nbtrack.cellidx[2]; nbtrack.cellidx_c[3] = csize*nbtrack.cellidx[3]; nbtrack.cellidx_c[4] = csize*nbtrack.cellidx[4]; nbtrack.cellidx_c[5] = csize*nbtrack.cellidx[5]; nbtrack.cellidx_c[6] = csize*nbtrack.cellidx[6]; nbtrack.cellidx_c[7] = csize*nbtrack.cellidx[7]; nbtrack.cellcnt = 0; nbtrack.pcnt = 0; } inline T *getNextNeighbor() { if (nbtrack.pcnt < occnt[nbtrack.cellidx[nbtrack.cellcnt]]) { return grid[nbtrack.cellidx_c[nbtrack.cellcnt] + (nbtrack.pcnt++)]; } else { for(;;) { nbtrack.cellcnt++; if (nbtrack.cellcnt >= 8) return 0; if (occnt[nbtrack.cellidx[nbtrack.cellcnt]] > 0) break; } nbtrack.pcnt = 1; return grid[nbtrack.cellidx_c[nbtrack.cellcnt]]; } } inline void createConnection(T *P1,int ep1, T *P2, int ep2) { if (ep1 == -1) P1->mID = P2->ID; else P1->pID = P2->ID; if (ep2 == -1) P2->mID = P1->ID; else P2->pID = P1->ID; concnt++; } inline void destroyConnection(T *P1,int ep1, T *P2, int ep2) { if (ep1 == -1) P1->mID = -1; else P1->pID = -1; if (ep2 == -1) P2->mID = -1; else P2->pID = -1; concnt--; } inline void destroyConnection(T *P1,int ep1) { T *P2 = 0; if (ep1 == 1) { P2 = ID_2_address[P1->pID]; P1->pID = -1; } else { P2 = ID_2_address[P1->mID]; P1->mID = -1; } if (P2->mID == P1->ID) { P2->mID = -1; } else { P2->pID = -1; } concnt--; } }; /* struct Connection { int lID; int rID; }; class ConnectionContainer { //////////////// Container public: Connection *cons; // cons in linear array int ccnt; // actual number of cons private: int capacity; // maximal number of particles public: ConnectionContainer() { //// involving the container capacity = 0; cons = 0; ccnt = 0; } void allocate(int _capacity) { //// involving the container capacity = _capacity; cons = (Connection*) malloc(sizeof(Connection)*capacity); ccnt = 0; } ~ConnectionContainer() { if (cons != 0) free(cons); } Connection* newConnection(int lid,int rid) { /////// get free place in container; if (ccnt < capacity) { Connection *c = &(cons[ccnt]); c->lID = lid; c->rID = rid; ccnt++; return c; } return 0; } inline void remove(int k) { Connection* c = &(cons[k]); // remove from container if (k #include "MersenneTwister.h" class RJMCMCBase { public: ParticleGrid m_ParticleGrid; float *m_QBallImageData; const int *datasz; EnergyComputerBase *enc; int m_Iterations; float width; float height; float depth; double *voxsize; int m_NumAttributes; int m_AcceptedProposals; RJMCMCBase(float *points,int numPoints, float *dimg, const int *dsz, double *voxsize, double cellsize) : m_QBallImageData(dimg) , datasz(dsz) , enc(0) , width(dsz[1]*voxsize[0]) , height(dsz[2]*voxsize[1]) , depth(dsz[3]*voxsize[2]) , voxsize(voxsize) , m_NumAttributes(0) , m_AcceptedProposals(0) { fprintf(stderr,"Data dimensions (mm) : %f x %f x %f\n",width,height,depth); fprintf(stderr,"Data dimensions (voxel) : %i x %i x %i\n",datasz[1],datasz[2],datasz[3]); fprintf(stderr,"voxel size (mm) : %lf x %lf x %lf\n",voxsize[0],voxsize[1],voxsize[2]); float cellcnt_x = (int)((float)width/cellsize) +1; float cellcnt_y = (int)((float)height/cellsize) +1; float cellcnt_z = (int)((float)depth/cellsize) +1; //int cell_capacity = 2048; //int cell_capacity = 64; int cell_capacity = 512; fprintf(stderr,"grid dimensions : %f x %f x %f\n",cellcnt_x,cellcnt_y,cellcnt_z); fprintf(stderr,"grid cell size (mm) : %f^3\n",cellsize); fprintf(stderr,"cell capacity : %i\n",cell_capacity); fprintf(stderr,"#cells*cellcap : %.1f K\n",cell_capacity*cellcnt_x*cellcnt_y*cellcnt_z/1000); int minsize = 1000000; int err = m_ParticleGrid.allocate(((numPoints>minsize)? (numPoints+100000) : minsize), cellcnt_x, cellcnt_y, cellcnt_z, cellsize, cell_capacity); if (err == -1) { fprintf(stderr,"RJMCMCBase: out of Memory!\n"); return; } m_NumAttributes = 10; for (int k = 0; k < numPoints; k++) { Particle *p = m_ParticleGrid.newParticle(pVector(points[m_NumAttributes*k], points[m_NumAttributes*k+1],points[m_NumAttributes*k+2])); if (p!=0) { p->N = pVector(points[m_NumAttributes*k+3],points[m_NumAttributes*k+4],points[m_NumAttributes*k+5]); p->cap = points[m_NumAttributes*k+6]; p->len = points[m_NumAttributes*k+7]; p->mID = (int) points[m_NumAttributes*k+8]; p->pID = (int) points[m_NumAttributes*k+9]; if (p->mID != -1) m_ParticleGrid.concnt++; if (p->pID != -1) m_ParticleGrid.concnt++; p->label = 0; } else { fprintf(stderr,"error: cannot allocate particle, con. indices will be wrong! \n"); } } m_ParticleGrid.concnt /= 2; m_Iterations = 0; m_AcceptedProposals = 0; } ~RJMCMCBase() { } void WriteOutParticles(float *npoints) { for (int k = 0; k < m_ParticleGrid.pcnt; k++) { Particle *p = &(m_ParticleGrid.particles[k]); npoints[m_NumAttributes*k] = p->R.GetX(); npoints[m_NumAttributes*k+1] = p->R.GetY(); npoints[m_NumAttributes*k+2] = p->R.GetZ(); npoints[m_NumAttributes*k+3] = p->N.GetX(); npoints[m_NumAttributes*k+4] = p->N.GetY(); npoints[m_NumAttributes*k+5] = p->N.GetZ(); npoints[m_NumAttributes*k+6] = p->cap; npoints[m_NumAttributes*k+7] = p->len; npoints[m_NumAttributes*k+8] = m_ParticleGrid.ID_2_index(p->mID); npoints[m_NumAttributes*k+9] = m_ParticleGrid.ID_2_index(p->pID); } } void SetEnergyComputer(EnergyComputerBase *e) { enc = e; } void Iterate(float* acceptance, unsigned long* numCon, unsigned long* numPart, bool *abort) { m_AcceptedProposals = 0; for (int it = 0; it < m_Iterations;it++) { if (*abort) break; IterateOneStep(); *numCon = m_ParticleGrid.concnt; *numPart = m_ParticleGrid.pcnt; } *acceptance = (float)m_AcceptedProposals/m_Iterations; } virtual void IterateOneStep() { } }; diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp index b1e927850e..0f15ef7675 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp @@ -1,620 +1,635 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "ParticleGrid.cpp" #include "RJMCMCBase.cpp" #include class RJMCMC : public RJMCMCBase { public: float T_in ; float T_ex ; float dens; float p_birth; float p_death; float p_shift; float p_shiftopt; float p_cap; float p_con; float sigma_g; float gamma_g; float Z_g; float dthres; float nthres; float T_prop; float stopprobability; float del_prob; float len_def; float len_sig; float cap_def; float cap_sig; float externalEnergy; float internalEnergy; float m_ChempotParticle; Track TrackProposal, TrackBackup; SimpSamp simpsamp; RJMCMC(float *points,int numPoints, float *dimg, const int *dsz, double *voxsz, double cellsz) : RJMCMCBase(points,numPoints,dimg,dsz,voxsz,cellsz) { externalEnergy = 0; internalEnergy = 0; } void SetParameters(float Temp, int numit, float plen, float curv_hardthres, float chempot_particle) { m_Iterations = numit; p_birth = 0.25; p_death = 0.05; p_shift = 0.15; p_shiftopt = 0.1; p_con = 0.45; p_cap = 0.0; m_ChempotParticle = chempot_particle; float sum = p_birth+p_death+p_shift+p_shiftopt+p_con; p_birth /= sum; p_death /= sum; p_shift /= sum; p_shiftopt /= sum; T_in = Temp; T_ex = 0.01; dens = exp(-chempot_particle/T_in); len_def = plen; len_sig = 0.0; cap_def = 1.0; cap_sig = 0.0; // shift proposal sigma_g = len_def/8.0; gamma_g = 1/(sigma_g*sigma_g*2); Z_g = pow(2*PI*sigma_g,3.0/2.0)*(PI*sigma_g/len_def); // conn proposal dthres = len_def; nthres = curv_hardthres; T_prop = 0.5; dthres *= dthres; stopprobability = exp(-1/T_prop); del_prob = 0.1; } void SetTemperature(float temp) { T_in = temp; dens = exp(-m_ChempotParticle/T_in); } void IterateOneStep() { float randnum = mtrand.frand(); //randnum = 0; /////////////////////////////////////////////////////////////// //////// Birth Proposal /////////////////////////////////////////////////////////////// if (randnum < p_birth) { #ifdef TIMING tic(&birthproposal_time); birthstats.propose(); #endif pVector R; enc->drawSpatPosition(&R); //fprintf(stderr,"drawn: %f, %f, %f\n",R[0],R[1],R[2]); //R.setXYZ(20.5*3, 35.5*3, 1.5*3); pVector N; N.rand_sphere(); //N.setXYZ(1,0,0); float cap = cap_def - cap_sig*mtrand.frand(); float len = len_def;// + len_sig*(mtrand.frand()-0.5); Particle prop; prop.R = R; prop.N = N; prop.cap = cap; prop.len = len; float prob = dens * p_death /((p_birth)*(m_ParticleGrid.pcnt+1)); float ex_energy = enc->computeExternalEnergy(R,N,cap,len,0); float in_energy = enc->computeInternalEnergy(&prop); prob *= exp((in_energy/T_in+ex_energy/T_ex)) ; if (prob > 1 || mtrand.frand() < prob) { Particle *p = m_ParticleGrid.newParticle(R); if (p!=0) { p->R = R; p->N = N; p->cap = cap; p->len = len; #ifdef TIMING birthstats.accepted(); #endif m_AcceptedProposals++; } } #ifdef TIMING toc(&birthproposal_time); #endif } /////////////////////////////////////////////////////////////// //////// Death Proposal /////////////////////////////////////////////////////////////// else if (randnum < p_birth+p_death) { if (m_ParticleGrid.pcnt > 0) { #ifdef TIMING tic(&deathproposal_time); deathstats.propose(); #endif int pnum = rand()%m_ParticleGrid.pcnt; Particle *dp = &(m_ParticleGrid.particles[pnum]); if (dp->pID == -1 && dp->mID == -1) { float ex_energy = enc->computeExternalEnergy(dp->R,dp->N,dp->cap,dp->len,dp); float in_energy = enc->computeInternalEnergy(dp); float prob = m_ParticleGrid.pcnt * (p_birth) /(dens*p_death); //*SpatProb(dp->R); prob *= exp(-(in_energy/T_in+ex_energy/T_ex)) ; if (prob > 1 || mtrand.frand() < prob) { m_ParticleGrid.remove(pnum); #ifdef TIMING deathstats.accepted(); #endif m_AcceptedProposals++; } } #ifdef TIMING toc(&deathproposal_time); #endif } } /////////////////////////////////////////////////////////////// //////// Cap change Proposal /////////////////////////////////////////////////////////////// else if (randnum < p_birth+p_death+p_cap) { if (m_ParticleGrid.pcnt > 0) { int pnum = rand()%m_ParticleGrid.pcnt; Particle *p = &(m_ParticleGrid.particles[pnum]); Particle prop_p = *p; prop_p.cap = cap_def - cap_sig*mtrand.frand(); float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,prop_p.cap,p->len,p) - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); //float in_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) // - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); float prob = exp(ex_energy/T_ex); // * SpatProb(p->R) / SpatProb(prop_p.R); if (mtrand.frand() < prob) { p->cap = prop_p.cap; m_AcceptedProposals++; } } } /////////////////////////////////////////////////////////////// //////// Shift Proposal /////////////////////////////////////////////////////////////// else if (randnum < p_birth+p_death+p_shift+p_cap) { float energy = 0; if (m_ParticleGrid.pcnt > 0) { #ifdef TIMING tic(&shiftproposal_time); shiftstats.propose(); #endif int pnum = rand()%m_ParticleGrid.pcnt; Particle *p = &(m_ParticleGrid.particles[pnum]); Particle prop_p = *p; prop_p.R.distortn(sigma_g); prop_p.N.distortn(sigma_g/(2*p->len)); prop_p.N.normalize(); float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); float in_energy = enc->computeInternalEnergy(&prop_p) - enc->computeInternalEnergy(p); float prob = exp(ex_energy/T_ex+in_energy/T_in); // * SpatProb(p->R) / SpatProb(prop_p.R); if (mtrand.frand() < prob) { pVector Rtmp = p->R; pVector Ntmp = p->N; p->R = prop_p.R; p->N = prop_p.N; if (!m_ParticleGrid.tryUpdateGrid(pnum)) { p->R = Rtmp; p->N = Ntmp; } #ifdef TIMING shiftstats.accepted(); #endif m_AcceptedProposals++; } #ifdef TIMING toc(&shiftproposal_time); #endif } } else if (randnum < p_birth+p_death+p_shift+p_shiftopt+p_cap) { float energy = 0; if (m_ParticleGrid.pcnt > 0) { int pnum = rand()%m_ParticleGrid.pcnt; Particle *p = &(m_ParticleGrid.particles[pnum]); bool no_proposal = false; Particle prop_p = *p; if (p->pID != -1 && p->mID != -1) { Particle *plus = m_ParticleGrid.ID_2_address[p->pID]; int ep_plus = (plus->pID == p->ID)? 1 : -1; Particle *minus = m_ParticleGrid.ID_2_address[p->mID]; int ep_minus = (minus->pID == p->ID)? 1 : -1; prop_p.R = (plus->R + plus->N * (plus->len * ep_plus) + minus->R + minus->N * (minus->len * ep_minus))*0.5; prop_p.N = plus->R - minus->R; prop_p.N.normalize(); } else if (p->pID != -1) { Particle *plus = m_ParticleGrid.ID_2_address[p->pID]; int ep_plus = (plus->pID == p->ID)? 1 : -1; prop_p.R = plus->R + plus->N * (plus->len * ep_plus * 2); prop_p.N = plus->N; } else if (p->mID != -1) { Particle *minus = m_ParticleGrid.ID_2_address[p->mID]; int ep_minus = (minus->pID == p->ID)? 1 : -1; prop_p.R = minus->R + minus->N * (minus->len * ep_minus * 2); prop_p.N = minus->N; } else no_proposal = true; if (!no_proposal) { float cos = prop_p.N*p->N; float p_rev = exp(-((prop_p.R-p->R).norm_square() + (1-cos*cos))*gamma_g)/Z_g; float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); float in_energy = enc->computeInternalEnergy(&prop_p) - enc->computeInternalEnergy(p); float prob = exp(ex_energy/T_ex+in_energy/T_in)*p_shift*p_rev/(p_shiftopt+p_shift*p_rev); //* SpatProb(p->R) / SpatProb(prop_p.R); if (mtrand.frand() < prob) { pVector Rtmp = p->R; pVector Ntmp = p->N; p->R = prop_p.R; p->N = prop_p.N; if (!m_ParticleGrid.tryUpdateGrid(pnum)) { p->R = Rtmp; p->N = Ntmp; } m_AcceptedProposals++; } } } } else { if (m_ParticleGrid.pcnt > 0) { #ifdef TIMING tic(&connproposal_time); connstats.propose(); #endif int pnum = rand()%m_ParticleGrid.pcnt; Particle *p = &(m_ParticleGrid.particles[pnum]); EndPoint P; P.p = p; P.ep = (mtrand.frand() > 0.5)? 1 : -1; RemoveAndSaveTrack(P); if (TrackBackup.proposal_probability != 0) { MakeTrackProposal(P); float prob = (TrackProposal.energy-TrackBackup.energy)/T_in ; // prob = exp(prob)*(TrackBackup.proposal_probability) // /(TrackProposal.proposal_probability); prob = exp(prob)*(TrackBackup.proposal_probability * pow(del_prob,TrackProposal.length)) /(TrackProposal.proposal_probability * pow(del_prob,TrackBackup.length)); if (mtrand.frand() < prob) { ImplementTrack(TrackProposal); #ifdef TIMING connstats.accepted(); #endif m_AcceptedProposals++; } else { ImplementTrack(TrackBackup); } } else ImplementTrack(TrackBackup); #ifdef TIMING toc(&connproposal_time); #endif } } } void ImplementTrack(Track &T) { for (int k = 1; k < T.length;k++) { m_ParticleGrid.createConnection(T.track[k-1].p,T.track[k-1].ep,T.track[k].p,-T.track[k].ep); } } void RemoveAndSaveTrack(EndPoint P) { EndPoint Current = P; int cnt = 0; float energy = 0; float AccumProb = 1.0; TrackBackup.track[cnt] = Current; EndPoint Next; for (;;) { Next.p = 0; if (Current.ep == 1) { if (Current.p->pID != -1) { Next.p = m_ParticleGrid.ID_2_address[Current.p->pID]; Current.p->pID = -1; m_ParticleGrid.concnt--; } } else if (Current.ep == -1) { if (Current.p->mID != -1) { Next.p = m_ParticleGrid.ID_2_address[Current.p->mID]; Current.p->mID = -1; m_ParticleGrid.concnt--; } } else { fprintf(stderr,"RJMCMC_randshift: Connection inconsistent 3\n"); break; } if (Next.p == 0) // no successor { Next.ep = 0; // mark as empty successor break; } else { if (Next.p->pID == Current.p->ID) { Next.p->pID = -1; Next.ep = 1; } else if (Next.p->mID == Current.p->ID) { Next.p->mID = -1; Next.ep = -1; } else { fprintf(stderr,"RJMCMC_randshift: Connection inconsistent 4\n"); break; } } ComputeEndPointProposalDistribution(Current); AccumProb *= (simpsamp.probFor(Next)); if (Next.p == 0) // no successor -> break break; energy += enc->computeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); Current = Next; Current.ep *= -1; cnt++; TrackBackup.track[cnt] = Current; if (mtrand.rand() > del_prob) { break; } } TrackBackup.energy = energy; TrackBackup.proposal_probability = AccumProb; TrackBackup.length = cnt+1; } void MakeTrackProposal(EndPoint P) { EndPoint Current = P; int cnt = 0; float energy = 0; float AccumProb = 1.0; TrackProposal.track[cnt++] = Current; Current.p->label = 1; for (;;) { // next candidate is already connected if ((Current.ep == 1 && Current.p->pID != -1) || (Current.ep == -1 && Current.p->mID != -1)) break; // track too long if (cnt > 250) break; ComputeEndPointProposalDistribution(Current); // // no candidates anymore // if (simpsamp.isempty()) // break; int k = simpsamp.draw(); // stop tracking proposed if (k==0) break; EndPoint Next = simpsamp.objs[k]; float probability = simpsamp.probFor(k); // accumulate energy and proposal distribution energy += enc->computeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); AccumProb *= probability; // track to next endpoint Current = Next; Current.ep *= -1; Current.p->label = 1; // put label to avoid loops TrackProposal.track[cnt++] = Current; } TrackProposal.energy = energy; TrackProposal.proposal_probability = AccumProb; TrackProposal.length = cnt; // clear labels for (int j = 0; j < TrackProposal.length;j++) { TrackProposal.track[j].p->label = 0; } } void ComputeEndPointProposalDistribution(EndPoint P) { Particle *p = P.p; int ep = P.ep; float dist,dot; pVector R = p->R + (p->N * ep*p->len); m_ParticleGrid.computeNeighbors(R); simpsamp.clear(); simpsamp.add(stopprobability,EndPoint(0,0)); for (;;) { Particle *p2 = m_ParticleGrid.getNextNeighbor(); if (p2 == 0) break; if (p!=p2 && p2->label == 0) { if (p2->mID == -1) { dist = (p2->R - p2->N * p2->len - R).norm_square(); if (dist < dthres) { dot = p2->N*p->N * ep; if (dot > nthres) { float en = enc->computeInternalEnergyConnection(p,ep,p2,-1); simpsamp.add(exp(en/T_prop),EndPoint(p2,-1)); } } } if (p2->pID == -1) { dist = (p2->R + p2->N * p2->len - R).norm_square(); if (dist < dthres) { dot = p2->N*p->N * (-ep); if (dot > nthres) { float en = enc->computeInternalEnergyConnection(p,ep,p2,+1); simpsamp.add(exp(en/T_prop),EndPoint(p2,+1)); } } } } } } }; diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp index 0f37dd624d..f13bfbd18b 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp @@ -1,122 +1,137 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "auxilary_classes.cpp" class SphereInterpolator { public: float *barycoords; int *indices; int size; // size of LUT int sN; // (sizeofLUT-1)/2 int nverts; // number of data vertices float beta; float inva; float b; int *idx; float *interpw; SphereInterpolator(float *barycoords, int *indices, int numverts, int sizeLUT, float beta) { this->barycoords = barycoords; this->indices = indices; this->size = sizeLUT; this->sN = (sizeLUT-1)/2; this->nverts = numverts; this->beta = beta; inva = (sqrt(1+beta)-sqrt(beta)); b = 1/(1-sqrt(1/beta + 1)); } inline void getInterpolation(vnl_vector_fixed N) { float nx = N[0]; float ny = N[1]; float nz = N[2]; if (nz > 0.5) { int x = float2int(nx); int y = float2int(ny); int i = 3*6*(x+y*size); // (:,1,x,y) idx = indices+i; interpw = barycoords +i; return; } if (nz < -0.5) { int x = float2int(nx); int y = float2int(ny); int i = 3*(1+6*(x+y*size)); // (:,2,x,y) idx = indices+i; interpw = barycoords +i; return; } if (nx > 0.5) { int z = float2int(nz); int y = float2int(ny); int i = 3*(2+6*(z+y*size)); // (:,2,x,y) idx = indices+i; interpw = barycoords +i; return; } if (nx < -0.5) { int z = float2int(nz); int y = float2int(ny); int i = 3*(3+6*(z+y*size)); // (:,2,x,y) idx = indices+i; interpw = barycoords +i; return; } if (ny > 0) { int x = float2int(nx); int z = float2int(nz); int i = 3*(4+6*(x+z*size)); // (:,1,x,y) idx = indices+i; interpw = barycoords +i; return; } else { int x = float2int(nx); int z = float2int(nz); int i = 3*(5+6*(x+z*size)); // (:,1,x,y) idx = indices+i; interpw = barycoords +i; return; } } inline float invrescale(float f) { float x = (fabs(f)-b)*inva; if (f>0) return (x*x-beta); else return beta - x*x; } inline int float2int(float x) { return int((invrescale(x)+1)*sN-0.5); } }; diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp index 24e7310e0f..297649be37 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp @@ -1,643 +1,658 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _AUXCLASS #define _AUXCLASS #ifndef INFINITY #define INFINITY 1000000000 #endif //#define INLINE __attribute__ ((always_inline)) #define INLINE inline //#define __SSE2 #ifdef __SSE2 #include class pVector { private: __m128 r; public: static float store[4]; pVector() { } pVector(__m128 q) { r = q; } pVector(float x,float y,float z) { r = _mm_set_ps(0,z,y,x); } INLINE void storeXYZ() { _mm_store_ps(store,r); } INLINE void setXYZ(float sx,float sy,float sz) { r = _mm_set_ps(0,sz,sy,sx); } INLINE void rand(float w,float h,float d) { float x = mtrand.frand()*w; float y = mtrand.frand()*h; float z = mtrand.frand()*d; r = _mm_set_ps(0,z,y,x); } INLINE void rand_sphere() { r = _mm_set_ps(0,mtrand.frandn(),mtrand.frandn(),mtrand.frandn()); normalize(); } INLINE void normalize() { __m128 q = _mm_mul_ps(r,r); _mm_store_ps(store,q); float norm = sqrt(store[0]+store[1]+store[2]) + 0.00000001; q = _mm_set_ps1(1/norm); r = _mm_mul_ps(r,q); } INLINE float norm_square() { __m128 q = _mm_mul_ps(r,r); _mm_store_ps(store,q); return store[0]+store[1]+store[2]; } INLINE void distortn(float sigma) { __m128 s = _mm_set_ps(0,mtrand.frandn(),mtrand.frandn(),mtrand.frandn()); __m128 q = _mm_set_ps1(sigma); r = _mm_add_ps(r,_mm_mul_ps(q,s)); } INLINE pVector operator*(float s) { __m128 q = _mm_set_ps1(s); return pVector(_mm_mul_ps(q,r)); } INLINE void operator*=(float &s) { __m128 q = _mm_set_ps1(s); r = _mm_mul_ps(q,r); } INLINE pVector operator+(pVector R) { return pVector(_mm_add_ps(R.r,r)); } INLINE void operator+=(pVector R) { r = _mm_add_ps(r,R.r); } INLINE pVector operator-(pVector R) { return pVector(_mm_sub_ps(r,R.r)); } INLINE void operator-=(pVector R) { r = _mm_sub_ps(r,R.r); } INLINE pVector operator/(float &s) { __m128 q = _mm_set_ps1(s); return pVector(_mm_div_ps(q,r)); } INLINE void operator/=(float &s) { __m128 q = _mm_set_ps1(s); r = _mm_div_ps(r,q); } INLINE float operator*(pVector R) { __m128 q = _mm_mul_ps(r,R.r); _mm_store_ps(store,q); return store[0]+store[1]+store[2]; } }; float pVector::store[4]; #else class pVector { private: float x; float y; float z; public: pVector() { } pVector(float x,float y,float z) { this->x = x; this->y = y; this->z = z; } INLINE void SetXYZ(float sx,float sy, float sz) { x = sx; y = sy; z = sz; } INLINE void GetXYZ(float *xyz) { xyz[0] = x; xyz[1] = y; xyz[2] = z; } INLINE float GetX() { return x; } INLINE float GetY() { return y; } INLINE float GetZ() { return z; } INLINE void rand(float w, float h, float d) { this->x = mtrand.frand()*w; this->y = mtrand.frand()*h; this->z = mtrand.frand()*d; } INLINE void rand_sphere() { this->x = mtrand.frandn(); this->y = mtrand.frandn(); this->z = mtrand.frandn(); normalize(); } INLINE void normalize() { float norm = sqrt(x*x+y*y+z*z)+ 0.00000001; *this /= norm; } INLINE float norm_square() { return x*x + y*y + z*z; } INLINE void distortn(float sigma) { x += sigma*mtrand.frandn(); y += sigma*mtrand.frandn(); z += sigma*mtrand.frandn(); } INLINE float operator[](int index) { switch(index) { case 0: return x; case 1: return y; case 2: return z; default: return 0.0f; } } INLINE pVector operator*(float s) { return pVector(s*x,s*y,s*z); } INLINE void operator*=(float &s) { x *= s; y *= s; z *= s; } INLINE pVector operator+(pVector R) { return pVector(x+R.x,y+R.y,z+R.z); } INLINE void operator+=(pVector R) { x += R.x; y += R.y; z += R.z; } INLINE pVector operator-(pVector R) { return pVector(x-R.x,y-R.y,z-R.z); } INLINE void operator-=(pVector R) { x -= R.x; y -= R.y; z -= R.z; } INLINE pVector operator/(float &s) { return pVector(x/s,y/s,z/s); } INLINE void operator/=(float &s) { x /= s; y /= s; z /= s; } INLINE float operator*(pVector R) { return x*R.x+y*R.y+z*R.z; } }; #endif class Particle { public: Particle() { label = 0; pID = -1; mID = -1; inserted = false; } ~Particle() { } pVector R; pVector N; float cap; float len; int gridindex; // index in the grid where it is living int ID; int pID; int mID; int label; int numerator; bool inserted; }; class EnergyGradient { public: pVector gR; pVector gN; INLINE float norm2() { return gR.norm_square() + gN.norm_square(); } } ; template class SimpSamp { float *P; int cnt; public: T *objs; SimpSamp() { P = (float*) malloc(sizeof(float)*1000); objs = (T*) malloc(sizeof(T)*1000); } ~SimpSamp() { free(P); free(objs); } INLINE void clear() { cnt = 1; P[0] = 0; } INLINE void add(float p, T obj) { P[cnt] = P[cnt-1] + p; objs[cnt-1] = obj; cnt++; } // INLINE int draw() // { // float r = mtrand.frand()*P[cnt-1]; // for (int i = 1; i < cnt; i++) // { // if (r <= P[i]) // return i-1; // } // return cnt-2; // } INLINE int draw() { float r = mtrand.frand()*P[cnt-1]; int j; int rl = 1; int rh = cnt-1; while(rh != rl) { j = rl + (rh-rl)/2; if (r < P[j]) { rh = j; continue; } if (r > P[j]) { rl = j+1; continue; } break; } return rh-1; } INLINE T drawObj() { return objs[draw()]; } INLINE bool isempty() { if (cnt == 1) return true; else return false; } float probFor(int idx) { return (P[idx+1]-P[idx])/P[cnt-1]; } float probFor(T &t) { for (int i = 1; i< cnt;i++) { if (t == objs[i-1]) return probFor(i-1); } return 0; } }; class EndPoint { public: EndPoint() {} EndPoint(Particle *p,int ep) { this->p = p; this->ep = ep; } Particle *p; int ep; inline bool operator==(EndPoint P) { return (P.p == p) && (P.ep == ep); } }; class Track { public: EndPoint track[1000]; float energy; float proposal_probability; int length; void clear() { length = 0; energy = 0; proposal_probability = 1; } bool isequal(Track &t) { for (int i = 0; i < length;i++) { if (track[i].p != t.track[i].p || track[i].ep != t.track[i].ep) return false; } return true; } }; float getMax(float *arr, int cnt) { float max = arr[0]; for (int i = 1; i < cnt; i++) { if (arr[i] > max) max = arr[i]; } return max; } float getMin(float *arr, int cnt) { float min = arr[0]; for (int i = 1; i < cnt; i++) { if (arr[i] < min) min = arr[i]; } return min; } int getArgMin(float *arr, int cnt) { float min = arr[0]; int idx = 0; for (int i = 1; i < cnt; i++) { if (arr[i] < min) { min = arr[i]; idx = i; } } return idx; } inline float distLseg(pVector &R1,pVector &N1,pVector &R2,pVector &N2,float &len) { pVector D = R1-R2; float beta = N1*N2; float divisor = 1.001-beta*beta; float gamma1 = N1*D; float gamma2 = N2*D; float t,u; float EPdist[4]; pVector Q; float dist = 102400000.0; while(true) { t = -(gamma1+beta*gamma2) / divisor; u = (gamma1*beta+gamma2) / divisor; if (fabs(t) < len && fabs(u) < len) { Q = D + N1*t - N2*u; dist = Q*Q; break; } beta = len*beta; t = beta - gamma1; if (fabs(t) < len) { Q = D + N1*t - N2*len; float d = Q*Q; if (d < dist) dist = d; } t = -beta - gamma1; if (fabs(t) < len) { Q = D + N1*t + N2*len; float d = Q*Q; if (d < dist) dist = d; } u = beta + gamma2; if (fabs(u) < len) { Q = D + N1*len - N2*u; float d = Q*Q; if (d < dist) dist = d; } u = -beta + gamma2; if (fabs(u) < len) { Q = D - N1*len - N2*u; float d = Q*Q; if (d < dist) dist = d; } if (dist != 102400000.0) break; EPdist[0] = beta + gamma1 - gamma2; EPdist[1] = -beta + gamma1 + gamma2; EPdist[2] = -beta - gamma1 - gamma2; EPdist[3] = beta - gamma1 + gamma2; int c = getArgMin(EPdist,4); if (c==0) {t = +len; u = +len; } if (c==1) {t = +len; u = -len; } if (c==2) {t = -len; u = +len; } if (c==3) {t = -len; u = -len; } Q = D + N1*t - N2*u; dist = Q*Q; break; } return dist; } #endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp index d2ff40b4fc..2a8d03222d 100644 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp @@ -1,281 +1,296 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __pcRJMCMC_cpp__ #define __pcRJMCMC_cpp__ //#include "mex.h" //#include "matrix.h" #define _USE_MATH_DEFINES #include #include #include #include using namespace std; #define float float #define PI M_PI //#define INFINITY 99999999999.0 //#define TIMING #ifdef TIMING static struct timeval timeS; class PropStats { int N; int accept; public: void clear() { N = 0; accept = 0;} void propose() {N++;} void accepted() {accept++;} void report(const char *s) { //mexPrintf("%s #proposals: %8.2fk acceptratio: %.2f \% \n",s,1.0*N/1000.0,100.0*accept/N); } }; class Timing { public: Timing() { time = 0; ncalls = 0;} void clear() {time = 0; ncalls=0;} long time; int ncalls; void report(const char *s) { //mexPrintf("%s total: %10.2fms calls: %10.1fk t/call: %10.3fms \n",s,time/1000.0,1.0*ncalls/1000.0,1.0*time/ncalls); } void report_time(const char *s) { //mexPrintf("%s: %.2fms \n",s,time/1000.0); } }; inline void tic(Timing *t) { gettimeofday( &timeS, NULL); t->time -= (timeS.tv_sec*1000000 + timeS.tv_usec); t->ncalls++; } inline void toc(Timing *t) { gettimeofday( &timeS, NULL); t->time += (timeS.tv_sec*1000000 + timeS.tv_usec); } Timing externalenergy_time; Timing internalenergy_time; Timing odfeval_time; Timing total_time; Timing shiftproposal_time; Timing birthproposal_time; Timing deathproposal_time; Timing capproposal_time; Timing lenproposal_time; Timing connproposal_time; PropStats deathstats; PropStats birthstats; PropStats connstats; PropStats shiftstats; PropStats capstats; PropStats lenstats; #endif #include "MersenneTwister.h" MTRand mtrand; float *BESSEL_APPROXCOEFF; #include "EnergyComputer_connec.cpp" //#include "EnergyComputer_center.cpp" //#include "RJMCMC_singlegradprop.cpp" #include "RJMCMC_randshift.cpp" //void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) //{ - + // if(nrhs != 7 && nrhs != 8) { - -// printf(" wrong usage!!!.\n\n"); + +// printf(" wrong usage!!!.\n\n"); // return; -// } else if(nlhs>3) { -// printf("Too many output arguments\n"); +// } else if(nlhs>3) { +// printf("Too many output arguments\n"); // return; -// } - -// int pcnt = 0; -// const mxArray *Points; -// Points = prhs[pcnt++]; -// int numPoints = mxGetN(Points); +// } + +// int pcnt = 0; +// const mxArray *Points; +// Points = prhs[pcnt++]; +// int numPoints = mxGetN(Points); // float *points = (float*) mxGetData(Points); - -// const mxArray *DataImg; -// DataImg = prhs[pcnt++]; + +// const mxArray *DataImg; +// DataImg = prhs[pcnt++]; // float *dimg = (float*) mxGetData(DataImg); -// const int *dsize = mxGetDimensions(DataImg); +// const int *dsize = mxGetDimensions(DataImg); -// const mxArray *Mask; -// Mask = prhs[pcnt++]; +// const mxArray *Mask; +// Mask = prhs[pcnt++]; // float *mask = (float*) mxGetData(Mask); // const int *dmsize = mxGetDimensions(Mask); // int mask_oversamp_mult = dmsize[0]/dsize[1]; -// const mxArray *VoxSize; -// VoxSize = prhs[pcnt++]; -// double *voxsize = (double*) mxGetPr(VoxSize); +// const mxArray *VoxSize; +// VoxSize = prhs[pcnt++]; +// double *voxsize = (double*) mxGetPr(VoxSize); -// const mxArray *Params; -// Params = prhs[pcnt++]; -// double *params = (double*) mxGetPr(Params); +// const mxArray *Params; +// Params = prhs[pcnt++]; +// double *params = (double*) mxGetPr(Params); // float Temp = (float) params[0]; -// int numit = (int) params[1]; +// int numit = (int) params[1]; // float conprob = (float) params[2]; // float particle_weight = (float) params[3]; // float particle_width = (float) params[4]; // float particle_len = (float) params[5]; // float chempot_connection = (float) params[6]; // float chempot_particle = (float) params[7]; // float inex_balance = (float) params[8]; // float chempot2 = (float) params[9]; // float meanval_sq = (float) params[10]; // const mxArray *BesselExpansion; -// BesselExpansion = prhs[pcnt++]; +// BesselExpansion = prhs[pcnt++]; // BESSEL_APPROXCOEFF = (float*) mxGetData(BesselExpansion); -// // read spherical-interpolator data - -// const mxArray *sinterpstruct = prhs[pcnt++]; -// mxArray *Indices = mxGetField(sinterpstruct,0,"indices"); -// mxArray *BaryCoords = mxGetField(sinterpstruct,0,"barycoords"); -// mxArray *Beta = mxGetField(sinterpstruct,0,"beta"); -// mxArray *NumInterpPoints = mxGetField(sinterpstruct,0,"numpoints"); - +// // read spherical-interpolator data + +// const mxArray *sinterpstruct = prhs[pcnt++]; +// mxArray *Indices = mxGetField(sinterpstruct,0,"indices"); +// mxArray *BaryCoords = mxGetField(sinterpstruct,0,"barycoords"); +// mxArray *Beta = mxGetField(sinterpstruct,0,"beta"); +// mxArray *NumInterpPoints = mxGetField(sinterpstruct,0,"numpoints"); + // float *indimg = (float*) mxGetData(Indices); -// const int *isize = mxGetDimensions(Indices); -// int totsz = isize[0]*isize[1]*isize[2]*isize[3]; -// int *indeximg = (int*) malloc(sizeof(int)*totsz); -// for (int k =0;k < totsz;k++) -// indeximg[k] = int(indimg[k])-1; +// const int *isize = mxGetDimensions(Indices); +// int totsz = isize[0]*isize[1]*isize[2]*isize[3]; +// int *indeximg = (int*) malloc(sizeof(int)*totsz); +// for (int k =0;k < totsz;k++) +// indeximg[k] = int(indimg[k])-1; // float *barycoords = (float*) mxGetData(BaryCoords); // float *beta = (float*) mxGetData(Beta); // int nip = int(*((float*)mxGetData(NumInterpPoints))); - + // SphereInterpolator *sinterp = new SphereInterpolator(barycoords,indeximg,nip,isize[2],beta[0]); - -// double breakhandle = 0; -// const mxArray *BreakHandle; -// if (nrhs == 8) -// { -// BreakHandle = prhs[pcnt++]; -// breakhandle = *mxGetPr(BreakHandle); -// } - -// #ifdef TIMING -// externalenergy_time.clear(); -// internalenergy_time.clear(); -// odfeval_time.clear(); -// total_time.clear(); - -// shiftproposal_time.clear(); -// birthproposal_time.clear(); -// deathproposal_time.clear(); -// capproposal_time.clear(); -// lenproposal_time.clear(); -// connproposal_time.clear(); - -// deathstats.clear(); -// birthstats.clear(); -// connstats.clear(); -// shiftstats.clear(); -// capstats.clear(); -// lenstats.clear(); -// #endif - + +// double breakhandle = 0; +// const mxArray *BreakHandle; +// if (nrhs == 8) +// { +// BreakHandle = prhs[pcnt++]; +// breakhandle = *mxGetPr(BreakHandle); +// } + +// #ifdef TIMING +// externalenergy_time.clear(); +// internalenergy_time.clear(); +// odfeval_time.clear(); +// total_time.clear(); + +// shiftproposal_time.clear(); +// birthproposal_time.clear(); +// deathproposal_time.clear(); +// capproposal_time.clear(); +// lenproposal_time.clear(); +// connproposal_time.clear(); + +// deathstats.clear(); +// birthstats.clear(); +// connstats.clear(); +// shiftstats.clear(); +// capstats.clear(); +// lenstats.clear(); +// #endif + // float cellsize = 2*particle_len; // float curv_hardthres = 0.7; // fprintf(stderr,"setting up MH-sampler \n"); fflush(stderr); -// RJMCMC sampler(points,numPoints, dimg, dsize, voxsize, cellsize); +// RJMCMC sampler(points,numPoints, dimg, dsize, voxsize, cellsize); // fprintf(stderr,"setting up Energy-computer \n"); fflush(stderr); // EnergyComputer encomp(dimg,dsize,voxsize,sinterp,&(sampler.pcontainer),mask,mask_oversamp_mult); // fprintf(stderr,"setting up parameters\n"); fflush(stderr); -// sampler.setParameters(Temp,numit,conprob,particle_len,curv_hardthres,chempot_particle); -// sampler.setEnergyComputer(&encomp); +// sampler.setParameters(Temp,numit,conprob,particle_len,curv_hardthres,chempot_particle); +// sampler.setEnergyComputer(&encomp); // encomp.setParameters(particle_weight,particle_width,chempot_connection*particle_len*particle_len,particle_len,curv_hardthres,inex_balance,chempot2,meanval_sq); // fprintf(stderr,"starting to iterate\n"); fflush(stderr); -// sampler.iterate(breakhandle); - -// int cnt = sampler.pcontainer.pcnt; -// #ifdef TIMING -// mexPrintf("\nEnergy\n------------------------\n"); -// externalenergy_time.report("external "); -// odfeval_time.report("odfeval "); -// internalenergy_time.report("internal "); -// total_time.report_time("total energy comp. "); - -// mexPrintf("overhead for proposals und stuff:%.1fms\n", -// (total_time.time-(externalenergy_time.time+odfeval_time.time+internalenergy_time.time))/1000.0); - -// mexPrintf("\nProposals\n------------------------\n"); -// birthproposal_time.report("birth "); -// deathproposal_time.report("death "); -// shiftproposal_time.report("shift "); -// connproposal_time.report("conne "); -//// capproposal_time.report("capch "); -//// lenproposal_time.report("length "); -// mexPrintf("\n"); -// birthstats.report("birth "); -// deathstats.report("death "); -// shiftstats.report("shift "); -// connstats.report("conne "); -//// lenstats.report("length "); -//// capstats.report("capch "); -// mexPrintf("\n"); - - - -// #endif - - -// int dims[] = {sampler.attrcnt, sampler.pcontainer.pcnt}; +// sampler.iterate(breakhandle); + +// int cnt = sampler.pcontainer.pcnt; +// #ifdef TIMING +// mexPrintf("\nEnergy\n------------------------\n"); +// externalenergy_time.report("external "); +// odfeval_time.report("odfeval "); +// internalenergy_time.report("internal "); +// total_time.report_time("total energy comp. "); + +// mexPrintf("overhead for proposals und stuff:%.1fms\n", +// (total_time.time-(externalenergy_time.time+odfeval_time.time+internalenergy_time.time))/1000.0); + +// mexPrintf("\nProposals\n------------------------\n"); +// birthproposal_time.report("birth "); +// deathproposal_time.report("death "); +// shiftproposal_time.report("shift "); +// connproposal_time.report("conne "); +//// capproposal_time.report("capch "); +//// lenproposal_time.report("length "); +// mexPrintf("\n"); +// birthstats.report("birth "); +// deathstats.report("death "); +// shiftstats.report("shift "); +// connstats.report("conne "); +//// lenstats.report("length "); +//// capstats.report("capch "); +// mexPrintf("\n"); + + + +// #endif + + +// int dims[] = {sampler.attrcnt, sampler.pcontainer.pcnt}; // plhs[0] = mxCreateNumericArray(2,dims,mxGetClassID(Points),mxfloat); // float *npoints = (float*) mxGetData(plhs[0]); -// sampler.writeout(npoints); - +// sampler.writeout(npoints); + -// delete sinterp; -// free(indeximg); +// delete sinterp; +// free(indeximg); //} #endif diff --git a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.h b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.h index e4b0f53d37..d1a2020083 100644 --- a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.h +++ b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.h @@ -1,112 +1,127 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _itkSlowPolyLineParametricPathPath_h #define _itkSlowPolyLineParametricPathPath_h #include "itkPolyLineParametricPath.h" #include "itkVectorContainer.h" #include "itkContinuousIndex.h" #include "itkIndex.h" #include "itkOffset.h" #include "itkVector.h" namespace itk { /** \class SlowPolyLineParametricPath * \brief Represent a path of line segments through ND Space * * This class is intended to represent parametric paths through an image, where * the paths are composed of line segments. Each line segment traverses one * unit of input. A classic application of this class is the representation of * contours in 2D images, especially when the contours only need to be * approximately correct. Another use of a path is to guide the movement of an * iterator through an image. * * \sa EllipseParametricPath * \sa FourierSeriesPath * \sa OrthogonallyCorrectedParametricPath * \sa ParametricPath * \sa ChainCodePath * \sa Path * \sa ContinuousIndex * \sa Index * \sa Offset * \sa Vector * * \ingroup PathObjects */ template class ITK_EXPORT SlowPolyLineParametricPath : public PolyLineParametricPath< VDimension > { public: /** Standard class typedefs. */ typedef SlowPolyLineParametricPath Self; typedef PolyLineParametricPath Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Run-time type information (and related methods). */ itkTypeMacro(SlowPolyLineParametricPath, PolyLineParametricPath); /** Input type */ typedef typename Superclass::InputType InputType; /** Output type */ typedef typename Superclass::OutputType OutputType; /** Basic data-structure types used */ typedef typename Superclass::ContinuousIndexType ContinuousIndexType; typedef typename Superclass::IndexType IndexType; typedef typename Superclass::OffsetType OffsetType; typedef typename Superclass::PointType PointType; typedef typename Superclass::VectorType VectorType; typedef typename Superclass::VertexType VertexType; typedef typename Superclass::VertexListType VertexListType; typedef typename Superclass::VertexListPointer VertexListPointer; /** Increment the input variable passed by reference such that the ND index of * the path moves to its next vertex-connected (8-connected in 2D) neighbor. * Return the Index-space offset of the path from its prior input to its new * input. If the path is unable to increment, input is not changed and an * offset of Zero is returned. Children are not required to implement bounds * checking. * * This is a fairly slow, iterative algorithm that numerically converges to * the next index along the path, in a vertex-connected (8-connected in 2D) * fashion. When possible, children of this class should overload this * function with something more efficient. * * WARNING: This default implementation REQUIRES that the ND endpoint of * the path be either unique or coincident only with the startpoint, since it * uses the endpoint as a stopping condition. */ virtual OffsetType IncrementInput(InputType & input) const; ///** Evaluate the first derivative of the ND output with respect to the 1D // * input. This is an exact, algebraic function. */ //virtual VectorType EvaluateDerivative(const InputType & input) const; /** New() method for dynamic construction */ itkNewMacro( Self ); protected: SlowPolyLineParametricPath(); ~SlowPolyLineParametricPath(){} void PrintSelf(std::ostream& os, Indent indent) const; private: SlowPolyLineParametricPath(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkSlowPolyLineParametricPath.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.txx b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.txx index e0852d1614..0a42b2832f 100644 --- a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.txx +++ b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkSlowPolyLineParametricPath.txx @@ -1,115 +1,130 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _itkSlowPolyLineParametricPath_txx #define _itkSlowPolyLineParametricPath_txx #include "itkSlowPolyLineParametricPath.h" #include namespace itk { //template //typename SlowPolyLineParametricPath::VectorType //SlowPolyLineParametricPath //::EvaluateDerivative(const InputType & input) const //{ //} /** * Constructor */ template SlowPolyLineParametricPath ::SlowPolyLineParametricPath() { this->SetDefaultInputStepSize( 0.3 ); } template typename SlowPolyLineParametricPath::OffsetType SlowPolyLineParametricPath ::IncrementInput(InputType & input) const { int iterationCount; bool tooSmall; bool tooBig; InputType inputStepSize; InputType finalInputValue; OffsetType offset; IndexType currentImageIndex; IndexType nextImageIndex; IndexType finalImageIndex; iterationCount = 0; inputStepSize = this->GetDefaultInputStepSize(); // Are we already at (or past) the end of the input? finalInputValue = this->EndOfInput(); currentImageIndex = this->EvaluateToIndex( input ); finalImageIndex = this->EvaluateToIndex( finalInputValue ); offset = finalImageIndex - currentImageIndex; if( ( offset == this->GetZeroOffset() && input != this->StartOfInput() ) || ( input >=finalInputValue ) ) { return this->GetZeroOffset(); } do { if( iterationCount++ > 10000 ) {itkExceptionMacro(<<"Too many iterations");} nextImageIndex = this->EvaluateToIndex( input + inputStepSize ); offset = nextImageIndex - currentImageIndex; tooBig = false; tooSmall = ( offset == this->GetZeroOffset() ); if( tooSmall ) { // increase the input step size, but don't go past the end of the input inputStepSize *= 2; if( (input + inputStepSize) >= finalInputValue ){ //inputStepSize = finalInputValue - input; inputStepSize += this->GetDefaultInputStepSize(); } } else { // Search for an offset dimension that is too big for( unsigned int i=0; i= 2 || offset[i] <= -2 ); } if( tooBig ){ //inputStepSize /= 1.5; inputStepSize -= (this->GetDefaultInputStepSize()/0.5); } } } while( tooSmall || tooBig ); input += inputStepSize; return offset; } /** * Standard "PrintSelf" method */ template void SlowPolyLineParametricPath ::PrintSelf( std::ostream& os, Indent indent) const { Superclass::PrintSelf( os, indent ); } } // end namespaceitk #endif diff --git a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkStochasticTractographyFilter_SD.txx b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkStochasticTractographyFilter_SD.txx index a849e86119..5994b0211b 100644 --- a/Modules/DiffusionImaging/Tractography/StochasticTracking/itkStochasticTractographyFilter_SD.txx +++ b/Modules/DiffusionImaging/Tractography/StochasticTracking/itkStochasticTractographyFilter_SD.txx @@ -1,2586 +1,2601 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkStochasticTractographyFilter.h" namespace itk{ template< class TInputDWIImage, class TInputMaskImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputMaskImage, TOutputConnectivityImage > ::LoadDefaultSampleDirections( void ){ const unsigned int totalsd = 2562; double sdarray[totalsd][3] = { {0.850651, 0.525731, 6.12323e-17}, {-0.850651, 0.525731, 6.12323e-17}, {-0.850651 , -0.525731, 6.12323e-17}, {0.850651, -0.525731, 6.12323e-17}, {0.525731, 0, 0.850651}, {0.525731, 0, -0.850651}, {-0.525731, 6.43835e-17, -0.850651}, {-0.525731, 6.43835e-17, 0.850651}, {5.20873e-17, 0.850651, 0.525731}, {5.20873e-17, -0.850651, 0.525731}, {5.20873e-17, -0.850651, -0.525731}, {5.20873e-17, 0.850651, -0.525731}, {0, 0, 1}, {-0.309017, 0.5, 0.809017 }, {0.309017, 0.5, 0.809017}, {0.309017, -0.5, 0.809017}, {-0.309017, -0.5, 0.809017}, {0.309017, 0.5, -0.809017}, {-0.309017, 0.5, -0.809017}, {1.22465e-16, 0, -1}, {-0.309017 , -0.5, -0.809017}, {0.309017, -0.5, -0.809017}, {1, 0, 6.12323e-17}, {0.809017, -0.309017, 0.5}, {0.809017, 0.309017, 0.5}, {0.809017, 0.309017, -0.5}, {0.809017, -0.309017, -0.5 }, {-1, 1.22465e-16, 6.12323e-17}, {-0.809017, 0.309017, 0.5}, {-0.809017, -0.309017, 0.5}, {-0.809017, -0.309017, -0.5}, {-0.809017, 0.309017, -0.5}, {6.12323e-17, 1, 6.12323e-17 }, {0.5, 0.809017, -0.309017}, {0.5, 0.809017, 0.309017}, {-0.5, 0.809017, 0.309017}, {-0.5, 0.809017, -0.309017}, {0.5, -0.809017, 0.309017}, {0.5, -0.809017, -0.309017}, { 6.12323e-17, -1, 6.12323e-17}, {-0.5, -0.809017, -0.309017}, {-0.5, -0.809017, 0.309017}, {0.273267, 0, 0.961938}, {0.16246, 0.262866, 0.951057}, {0.433889, 0.259892, 0.862668}, {- 0.273267, 3.34655e-17, 0.961938}, {-0.433889, 0.259892, 0.862668}, {-0.16246, 0.262866, 0.951057}, {-8.4544e-17, 0.525731, 0.850651}, {-0.160622, 0.702046, 0.69378}, {0.160622, 0.702046, 0.69378}, {0.433889, -0.259892, 0.862668}, {0.16246, -0.262866, 0.951057}, {0.160622, -0.702046, 0.69378}, {-0.160622, -0.702046, 0.69378}, {-8.4544e-17, -0.525731, 0.850651}, {-0.16246 , -0.262866, 0.951057}, {-0.433889, -0.259892, 0.862668}, {0.433889, 0.259892, -0.862668}, {0.16246, 0.262866, -0.951057}, {0.273267, 0, -0.961938}, {0.160622, 0.702046, -0.69378}, {- 0.160622, 0.702046, -0.69378}, {-8.4544e-17, 0.525731, -0.850651}, {-0.16246, 0.262866, -0.951057}, {-0.433889, 0.259892, -0.862668}, {-0.273267, 3.34655e-17, -0.961938}, {0.16246, -0.262866 , -0.951057}, {0.433889, -0.259892, -0.862668}, {-0.433889, -0.259892, -0.862668}, {-0.16246, -0.262866, -0.951057}, {-8.4544e-17, -0.525731, -0.850651}, {-0.160622, -0.702046, -0.69378}, {0.160622, -0.702046, -0.69378}, {0.961938, 0.273267, 6.12323e-17}, {0.951057, 0.16246, 0.262866}, {0.862668, 0.433889, 0.259892}, {0.961938, -0.273267, 6.12323e-17}, {0.862668, - 0.433889, 0.259892}, {0.951057, -0.16246, 0.262866}, {0.850651, 0, 0.525731}, {0.69378, -0.160622, 0.702046}, {0.69378, 0.160622, 0.702046}, {0.862668, 0.433889, -0.259892}, {0.951057 , 0.16246, -0.262866}, {0.69378, 0.160622, -0.702046}, {0.69378, -0.160622, -0.702046}, {0.850651, 0, -0.525731}, {0.951057, -0.16246, -0.262866}, {0.862668, -0.433889, -0.259892}, {- 0.961938, -0.273267, 6.12323e-17}, {-0.951057, -0.16246, 0.262866}, {-0.862668, -0.433889, 0.259892}, {-0.961938, 0.273267, 6.12323e-17}, {-0.862668, 0.433889, 0.259892}, {-0.951057, 0.16246 , 0.262866}, {-0.850651, 1.04175e-16, 0.525731}, {-0.69378, 0.160622, 0.702046}, {-0.69378, -0.160622, 0.702046}, {-0.862668, -0.433889, -0.259892}, {-0.951057, -0.16246, -0.262866}, {-0.69378, -0.160622, -0.702046}, {-0.69378, 0.160622, -0.702046}, {-0.850651, 1.04175e-16, -0.525731}, {-0.951057, 0.16246, -0.262866}, {-0.862668, 0.433889, -0.259892}, {5.89017e-17 , 0.961938, 0.273267}, {0.262866, 0.951057, 0.16246}, {0.259892, 0.862668, 0.433889}, {5.89017e-17, 0.961938, -0.273267}, {0.259892, 0.862668, -0.433889}, {0.262866, 0.951057, -0.16246}, {0.525731, 0.850651, -1.60812e-16}, {0.702046, 0.69378, -0.160622}, {0.702046, 0.69378, 0.160622}, {-0.259892, 0.862668, 0.433889}, {-0.262866, 0.951057, 0.16246}, {-0.702046, 0.69378 , 0.160622}, {-0.702046, 0.69378, -0.160622}, {-0.525731, 0.850651, -1.60812e-16}, {-0.262866, 0.951057, -0.16246}, {-0.259892, 0.862668, -0.433889}, {0.259892, -0.862668, 0.433889}, {0.262866, -0.951057, 0.16246}, {5.89017e-17, -0.961938, 0.273267}, {0.702046, -0.69378, 0.160622}, {0.702046, -0.69378, -0.160622}, {0.525731, -0.850651, -1.60812e-16}, {0.262866, - 0.951057, -0.16246}, {0.259892, -0.862668, -0.433889}, {5.89017e-17, -0.961938, -0.273267}, {-0.262866, -0.951057, 0.16246}, {-0.259892, -0.862668, 0.433889}, {-0.259892, -0.862668, -0.433889 }, {-0.262866, -0.951057, -0.16246}, {-0.525731, -0.850651, -1.60812e-16}, {-0.702046, -0.69378, -0.160622}, {-0.702046, -0.69378, 0.160622}, {0.425325, 0.688191, 0.587785}, {0.688191 , 0.587785, 0.425325}, {0.587785, 0.425325, 0.688191}, {0.425325, 0.688191, -0.587785}, {0.587785, 0.425325, -0.688191}, {0.688191, 0.587785, -0.425325}, {0.587785, -0.425325, 0.688191}, {0.688191, -0.587785, 0.425325}, {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, -0.688191}, {0.425325, -0.688191, -0.587785}, {0.688191, -0.587785, -0.425325}, {-0.587785 , 0.425325, 0.688191}, {-0.688191, 0.587785, 0.425325}, {-0.425325, 0.688191, 0.587785}, {-0.587785, 0.425325, -0.688191}, {-0.425325, 0.688191, -0.587785}, {-0.688191, 0.587785, -0.425325 }, {-0.587785, -0.425325, 0.688191}, {-0.425325, -0.688191, 0.587785}, {-0.688191, -0.587785, 0.425325}, {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325}, {-0.425325 , -0.688191, -0.587785}, {0.403355, 0, 0.915043}, {0.358229, 0.131655, 0.924305}, {0.484442, 0.1312, 0.864929}, {0.137952, 0, 0.990439}, {0.0822425, 0.133071, 0.987688}, {0.220117 , 0.132792, 0.966393}, {0.301259, 0.264083, 0.916244}, {0.238677, 0.386187, 0.891007}, {0.375039, 0.383614, 0.843911}, {-0.137952, 1.68943e-17, 0.990439}, {-0.220117, 0.132792, 0.966393}, {-0.0822425, 0.133071, 0.987688}, {-0.403355, 4.93968e-17, 0.915043}, {-0.484442, 0.1312, 0.864929}, {-0.358229, 0.131655, 0.924305}, {-0.301259, 0.264083, 0.916244}, {-0.375039, 0.383614, 0.843911}, {-0.238677, 0.386187, 0.891007}, {0.156434, 0.519258, 0.840178}, {0.0811419, 0.62024, 0.780204}, {0.237086, 0.606825, 0.758652}, {-0.156434, 0.519258, 0.840178}, {-0.237086, 0.606825, 0.758652}, {-0.0811419, 0.62024, 0.780204}, {-1.14383e-16, 0.711282, 0.702907}, {-0.0810863, 0.783843, 0.615642}, {0.0810863, 0.783843, 0.615642}, {-4.28411e-17 , 0.266405, 0.963861}, {-0.0823236, 0.399607, 0.912982}, {0.0823236, 0.399607, 0.912982}, {0.484442, -0.1312, 0.864929}, {0.358229, -0.131655, 0.924305}, {0.375039, -0.383614, 0.843911}, {0.238677, -0.386187, 0.891007}, {0.301259, -0.264083, 0.916244}, {0.220117, -0.132792, 0.966393}, {0.0822425, -0.133071, 0.987688}, {0.237086, -0.606825, 0.758652}, {0.0811419, - 0.62024, 0.780204}, {0.156434, -0.519258, 0.840178}, {0.0810863, -0.783843, 0.615642}, {-0.0810863, -0.783843, 0.615642}, {-1.14383e-16, -0.711282, 0.702907}, {-0.0811419, -0.62024, 0.780204 }, {-0.237086, -0.606825, 0.758652}, {-0.156434, -0.519258, 0.840178}, {-0.0822425, -0.133071, 0.987688}, {-0.220117, -0.132792, 0.966393}, {-0.238677, -0.386187, 0.891007}, {-0.375039 , -0.383614, 0.843911}, {-0.301259, -0.264083, 0.916244}, {-0.358229, -0.131655, 0.924305}, {-0.484442, -0.1312, 0.864929}, {0.0823236, -0.399607, 0.912982}, {-0.0823236, -0.399607, 0.912982 }, {-4.28411e-17, -0.266405, 0.963861}, {0.484442, 0.1312, -0.864929}, {0.358229, 0.131655, -0.924305}, {0.403355, 0, -0.915043}, {0.375039, 0.383614, -0.843911}, {0.238677, 0.386187 , -0.891007}, {0.301259, 0.264083, -0.916244}, {0.220117, 0.132792, -0.966393}, {0.0822425, 0.133071, -0.987688}, {0.137952, 0, -0.990439}, {0.237086, 0.606825, -0.758652}, {0.0811419 , 0.62024, -0.780204}, {0.156434, 0.519258, -0.840178}, {0.0810863, 0.783843, -0.615642}, {-0.0810863, 0.783843, -0.615642}, {4.35534e-17, 0.711282, -0.702907}, {-0.0811419, 0.62024, -0.780204 }, {-0.237086, 0.606825, -0.758652}, {-0.156434, 0.519258, -0.840178}, {-0.0822425, 0.133071, -0.987688}, {-0.220117, 0.132792, -0.966393}, {-0.137952, 1.68943e-17, -0.990439}, {- 0.238677, 0.386187, -0.891007}, {-0.375039, 0.383614, -0.843911}, {-0.301259, 0.264083, -0.916244}, {-0.358229, 0.131655, -0.924305}, {-0.484442, 0.1312, -0.864929}, {-0.403355, 4.93968e-17 , -0.915043}, {0.0823236, 0.399607, -0.912982}, {-0.0823236, 0.399607, -0.912982}, {1.63126e-17, 0.266405, -0.963861}, {0.358229, -0.131655, -0.924305}, {0.484442, -0.1312, -0.864929}, {0.0822425, -0.133071, -0.987688}, {0.220117, -0.132792, -0.966393}, {0.301259, -0.264083, -0.916244}, {0.238677, -0.386187, -0.891007}, {0.375039, -0.383614, -0.843911}, {-0.220117, - 0.132792, -0.966393}, {-0.0822425, -0.133071, -0.987688}, {-0.484442, -0.1312, -0.864929}, {-0.358229, -0.131655, -0.924305}, {-0.301259, -0.264083, -0.916244}, {-0.375039, -0.383614, -0.843911 }, {-0.238677, -0.386187, -0.891007}, {0.156434, -0.519258, -0.840178}, {0.0811419, -0.62024, -0.780204}, {0.237086, -0.606825, -0.758652}, {-0.156434, -0.519258, -0.840178}, {-0.237086 , -0.606825, -0.758652}, {-0.0811419, -0.62024, -0.780204}, {4.35534e-17, -0.711282, -0.702907}, {-0.0810863, -0.783843, -0.615642}, {0.0810863, -0.783843, -0.615642}, {1.63126e-17, -0.266405 , -0.963861}, {-0.0823236, -0.399607, -0.912982}, {0.0823236, -0.399607, -0.912982}, {0.915043, 0.403355, 6.12323e-17}, {0.924305, 0.358229, 0.131655}, {0.864929, 0.484442, 0.1312}, { 0.990439, 0.137952, 6.12323e-17}, {0.987688, 0.0822425, 0.133071}, {0.966393, 0.220117, 0.132792}, {0.916244, 0.301259, 0.264083}, {0.891007, 0.238677, 0.386187}, {0.843911, 0.375039, 0.383614 }, {0.990439, -0.137952, 6.12323e-17}, {0.966393, -0.220117, 0.132792}, {0.987688, -0.0822425, 0.133071}, {0.915043, -0.403355, 6.12323e-17}, {0.864929, -0.484442, 0.1312}, {0.924305 , -0.358229, 0.131655}, {0.916244, -0.301259, 0.264083}, {0.843911, -0.375039, 0.383614}, {0.891007, -0.238677, 0.386187}, {0.840178, 0.156434, 0.519258}, {0.780204, 0.0811419, 0.62024}, {0.758652, 0.237086, 0.606825}, {0.840178, -0.156434, 0.519258}, {0.758652, -0.237086, 0.606825}, {0.780204, -0.0811419, 0.62024}, {0.702907, 0, 0.711282}, {0.615642, -0.0810863, 0.783843}, {0.615642, 0.0810863, 0.783843}, {0.963861, 0, 0.266405}, {0.912982, -0.0823236, 0.399607}, {0.912982, 0.0823236, 0.399607}, {0.864929, 0.484442, -0.1312}, {0.924305, 0.358229 , -0.131655}, {0.843911, 0.375039, -0.383614}, {0.891007, 0.238677, -0.386187}, {0.916244, 0.301259, -0.264083}, {0.966393, 0.220117, -0.132792}, {0.987688, 0.0822425, -0.133071}, { 0.758652, 0.237086, -0.606825}, {0.780204, 0.0811419, -0.62024}, {0.840178, 0.156434, -0.519258}, {0.615642, 0.0810863, -0.783843}, {0.615642, -0.0810863, -0.783843}, {0.702907, 0, -0.711282 }, {0.780204, -0.0811419, -0.62024}, {0.758652, -0.237086, -0.606825}, {0.840178, -0.156434, -0.519258}, {0.987688, -0.0822425, -0.133071}, {0.966393, -0.220117, -0.132792}, {0.891007 , -0.238677, -0.386187}, {0.843911, -0.375039, -0.383614}, {0.916244, -0.301259, -0.264083}, {0.924305, -0.358229, -0.131655}, {0.864929, -0.484442, -0.1312}, {0.912982, 0.0823236, -0.399607 }, {0.912982, -0.0823236, -0.399607}, {0.963861, 0, -0.266405}, {-0.915043, -0.403355, 6.12323e-17}, {-0.924305, -0.358229, 0.131655}, {-0.864929, -0.484442, 0.1312}, {-0.990439, - 0.137952, 6.12323e-17}, {-0.987688, -0.0822425, 0.133071}, {-0.966393, -0.220117, 0.132792}, {-0.916244, -0.301259, 0.264083}, {-0.891007, -0.238677, 0.386187}, {-0.843911, -0.375039, 0.383614 }, {-0.990439, 0.137952, 6.12323e-17}, {-0.966393, 0.220117, 0.132792}, {-0.987688, 0.0822425, 0.133071}, {-0.915043, 0.403355, 6.12323e-17}, {-0.864929, 0.484442, 0.1312}, {-0.924305 , 0.358229, 0.131655}, {-0.916244, 0.301259, 0.264083}, {-0.843911, 0.375039, 0.383614}, {-0.891007, 0.238677, 0.386187}, {-0.840178, -0.156434, 0.519258}, {-0.780204, -0.0811419, 0.62024 }, {-0.758652, -0.237086, 0.606825}, {-0.840178, 0.156434, 0.519258}, {-0.758652, 0.237086, 0.606825}, {-0.780204, 0.0811419, 0.62024}, {-0.702907, 8.60813e-17, 0.711282}, {-0.615642 , 0.0810863, 0.783843}, {-0.615642, -0.0810863, 0.783843}, {-0.963861, 1.18039e-16, 0.266405}, {-0.912982, 0.0823236, 0.399607}, {-0.912982, -0.0823236, 0.399607}, {-0.864929, -0.484442, - 0.1312}, {-0.924305, -0.358229, -0.131655}, {-0.843911, -0.375039, -0.383614}, {-0.891007, -0.238677, -0.386187}, {-0.916244, -0.301259, -0.264083}, {-0.966393, -0.220117, -0.132792}, {-0.987688, -0.0822425, -0.133071}, {-0.758652, -0.237086, -0.606825}, {-0.780204, -0.0811419, -0.62024}, {-0.840178, -0.156434, -0.519258}, {-0.615642, -0.0810863, -0.783843}, {-0.615642 , 0.0810863, -0.783843}, {-0.702907, 8.60813e-17, -0.711282}, {-0.780204, 0.0811419, -0.62024}, {-0.758652, 0.237086, -0.606825}, {-0.840178, 0.156434, -0.519258}, {-0.987688, 0.0822425, - 0.133071}, {-0.966393, 0.220117, -0.132792}, {-0.891007, 0.238677, -0.386187}, {-0.843911, 0.375039, -0.383614}, {-0.916244, 0.301259, -0.264083}, {-0.924305, 0.358229, -0.131655}, {- 0.864929, 0.484442, -0.1312}, {-0.912982, -0.0823236, -0.399607}, {-0.912982, 0.0823236, -0.399607}, {-0.963861, 1.18039e-16, -0.266405}, {5.60302e-17, 0.915043, 0.403355}, {0.131655, 0.924305 , 0.358229}, {0.1312, 0.864929, 0.484442}, {6.06469e-17, 0.990439, 0.137952}, {0.133071, 0.987688, 0.0822425}, {0.132792, 0.966393, 0.220117}, {0.264083, 0.916244, 0.301259}, {0.386187 , 0.891007, 0.238677}, {0.383614, 0.843911, 0.375039}, {6.06469e-17, 0.990439, -0.137952}, {0.132792, 0.966393, -0.220117}, {0.133071, 0.987688, -0.0822425}, {5.60302e-17, 0.915043, -0.403355 }, {0.1312, 0.864929, -0.484442}, {0.131655, 0.924305, -0.358229}, {0.264083, 0.916244, -0.301259}, {0.383614, 0.843911, -0.375039}, {0.386187, 0.891007, -0.238677}, {0.519258, 0.840178 , 0.156434}, {0.62024, 0.780204, 0.0811419}, {0.606825, 0.758652, 0.237086}, {0.519258, 0.840178, -0.156434}, {0.606825, 0.758652, -0.237086}, {0.62024, 0.780204, -0.0811419}, {0.711282 , 0.702907, -1.60812e-16}, {0.783843, 0.615642, -0.0810863}, {0.783843, 0.615642, 0.0810863}, {0.266405, 0.963861, -1.60812e-16}, {0.399607, 0.912982, -0.0823236}, {0.399607, 0.912982, 0.0823236 }, {-0.1312, 0.864929, 0.484442}, {-0.131655, 0.924305, 0.358229}, {-0.383614, 0.843911, 0.375039}, {-0.386187, 0.891007, 0.238677}, {-0.264083, 0.916244, 0.301259}, {-0.132792, 0.966393 , 0.220117}, {-0.133071, 0.987688, 0.0822425}, {-0.606825, 0.758652, 0.237086}, {-0.62024, 0.780204, 0.0811419}, {-0.519258, 0.840178, 0.156434}, {-0.783843, 0.615642, 0.0810863}, {- 0.783843, 0.615642, -0.0810863}, {-0.711282, 0.702907, -1.60812e-16}, {-0.62024, 0.780204, -0.0811419}, {-0.606825, 0.758652, -0.237086}, {-0.519258, 0.840178, -0.156434}, {-0.133071, 0.987688 , -0.0822425}, {-0.132792, 0.966393, -0.220117}, {-0.386187, 0.891007, -0.238677}, {-0.383614, 0.843911, -0.375039}, {-0.264083, 0.916244, -0.301259}, {-0.131655, 0.924305, -0.358229}, {-0.1312, 0.864929, -0.484442}, {-0.399607, 0.912982, 0.0823236}, {-0.399607, 0.912982, -0.0823236}, {-0.266405, 0.963861, -1.60812e-16}, {0.1312, -0.864929, 0.484442}, {0.131655, -0.924305 , 0.358229}, {5.60302e-17, -0.915043, 0.403355}, {0.383614, -0.843911, 0.375039}, {0.386187, -0.891007, 0.238677}, {0.264083, -0.916244, 0.301259}, {0.132792, -0.966393, 0.220117}, { 0.133071, -0.987688, 0.0822425}, {6.06469e-17, -0.990439, 0.137952}, {0.606825, -0.758652, 0.237086}, {0.62024, -0.780204, 0.0811419}, {0.519258, -0.840178, 0.156434}, {0.783843, -0.615642 , 0.0810863}, {0.783843, -0.615642, -0.0810863}, {0.711282, -0.702907, -1.60812e-16}, {0.62024, -0.780204, -0.0811419}, {0.606825, -0.758652, -0.237086}, {0.519258, -0.840178, -0.156434}, {0.133071, -0.987688, -0.0822425}, {0.132792, -0.966393, -0.220117}, {6.06469e-17, -0.990439, -0.137952}, {0.386187, -0.891007, -0.238677}, {0.383614, -0.843911, -0.375039}, {0.264083 , -0.916244, -0.301259}, {0.131655, -0.924305, -0.358229}, {0.1312, -0.864929, -0.484442}, {5.60302e-17, -0.915043, -0.403355}, {0.399607, -0.912982, 0.0823236}, {0.399607, -0.912982, -0.0823236 }, {0.266405, -0.963861, -1.60812e-16}, {-0.131655, -0.924305, 0.358229}, {-0.1312, -0.864929, 0.484442}, {-0.133071, -0.987688, 0.0822425}, {-0.132792, -0.966393, 0.220117}, {-0.264083 , -0.916244, 0.301259}, {-0.386187, -0.891007, 0.238677}, {-0.383614, -0.843911, 0.375039}, {-0.132792, -0.966393, -0.220117}, {-0.133071, -0.987688, -0.0822425}, {-0.1312, -0.864929, -0.484442 }, {-0.131655, -0.924305, -0.358229}, {-0.264083, -0.916244, -0.301259}, {-0.383614, -0.843911, -0.375039}, {-0.386187, -0.891007, -0.238677}, {-0.519258, -0.840178, 0.156434}, {- 0.62024, -0.780204, 0.0811419}, {-0.606825, -0.758652, 0.237086}, {-0.519258, -0.840178, -0.156434}, {-0.606825, -0.758652, -0.237086}, {-0.62024, -0.780204, -0.0811419}, {-0.711282, -0.702907 , -1.60812e-16}, {-0.783843, -0.615642, -0.0810863}, {-0.783843, -0.615642, 0.0810863}, {-0.266405, -0.963861, -1.60812e-16}, {-0.399607, -0.912982, -0.0823236}, {-0.399607, -0.912982, 0.0823236 }, {0.213023, 0.792649, 0.571252}, {0.46843, 0.757935, 0.453991}, {0.346153, 0.783452, 0.516122}, {0.296005, 0.70231, 0.647412}, {0.371748, 0.601501, 0.707107}, {0.70231, 0.647412 , 0.296005}, {0.601501, 0.707107, 0.371748}, {0.792649, 0.571252, 0.213023}, {0.783452, 0.516122, 0.346153}, {0.757935, 0.453991, 0.46843}, {0.453991, 0.46843, 0.757935}, {0.516122 , 0.346153, 0.783452}, {0.707107, 0.371748, 0.601501}, {0.647412, 0.296005, 0.70231}, {0.571252, 0.213023, 0.792649}, {0.564254, 0.646578, 0.513375}, {0.646578, 0.513375, 0.564254}, { 0.513375, 0.564254, 0.646578}, {0.213023, 0.792649, -0.571252}, {0.371748, 0.601501, -0.707107}, {0.296005, 0.70231, -0.647412}, {0.346153, 0.783452, -0.516122}, {0.46843, 0.757935, -0.453991 }, {0.516122, 0.346153, -0.783452}, {0.453991, 0.46843, -0.757935}, {0.571252, 0.213023, -0.792649}, {0.647412, 0.296005, -0.70231}, {0.707107, 0.371748, -0.601501}, {0.601501, 0.707107 , -0.371748}, {0.70231, 0.647412, -0.296005}, {0.757935, 0.453991, -0.46843}, {0.783452, 0.516122, -0.346153}, {0.792649, 0.571252, -0.213023}, {0.513375, 0.564254, -0.646578}, {0.646578 , 0.513375, -0.564254}, {0.564254, 0.646578, -0.513375}, {0.571252, -0.213023, 0.792649}, {0.707107, -0.371748, 0.601501}, {0.647412, -0.296005, 0.70231}, {0.516122, -0.346153, 0.783452}, {0.453991, -0.46843, 0.757935}, {0.783452, -0.516122, 0.346153}, {0.757935, -0.453991, 0.46843}, {0.792649, -0.571252, 0.213023}, {0.70231, -0.647412, 0.296005}, {0.601501, -0.707107 , 0.371748}, {0.371748, -0.601501, 0.707107}, {0.296005, -0.70231, 0.647412}, {0.46843, -0.757935, 0.453991}, {0.346153, -0.783452, 0.516122}, {0.213023, -0.792649, 0.571252}, {0.646578 , -0.513375, 0.564254}, {0.564254, -0.646578, 0.513375}, {0.513375, -0.564254, 0.646578}, {0.571252, -0.213023, -0.792649}, {0.453991, -0.46843, -0.757935}, {0.516122, -0.346153, -0.783452 }, {0.647412, -0.296005, -0.70231}, {0.707107, -0.371748, -0.601501}, {0.296005, -0.70231, -0.647412}, {0.371748, -0.601501, -0.707107}, {0.213023, -0.792649, -0.571252}, {0.346153 , -0.783452, -0.516122}, {0.46843, -0.757935, -0.453991}, {0.757935, -0.453991, -0.46843}, {0.783452, -0.516122, -0.346153}, {0.601501, -0.707107, -0.371748}, {0.70231, -0.647412, -0.296005 }, {0.792649, -0.571252, -0.213023}, {0.513375, -0.564254, -0.646578}, {0.564254, -0.646578, -0.513375}, {0.646578, -0.513375, -0.564254}, {-0.571252, 0.213023, 0.792649}, {-0.707107 , 0.371748, 0.601501}, {-0.647412, 0.296005, 0.70231}, {-0.516122, 0.346153, 0.783452}, {-0.453991, 0.46843, 0.757935}, {-0.783452, 0.516122, 0.346153}, {-0.757935, 0.453991, 0.46843}, {-0.792649, 0.571252, 0.213023}, {-0.70231, 0.647412, 0.296005}, {-0.601501, 0.707107, 0.371748}, {-0.371748, 0.601501, 0.707107}, {-0.296005, 0.70231, 0.647412}, {-0.46843, 0.757935 , 0.453991}, {-0.346153, 0.783452, 0.516122}, {-0.213023, 0.792649, 0.571252}, {-0.646578, 0.513375, 0.564254}, {-0.564254, 0.646578, 0.513375}, {-0.513375, 0.564254, 0.646578}, {- 0.571252, 0.213023, -0.792649}, {-0.453991, 0.46843, -0.757935}, {-0.516122, 0.346153, -0.783452}, {-0.647412, 0.296005, -0.70231}, {-0.707107, 0.371748, -0.601501}, {-0.296005, 0.70231, - 0.647412}, {-0.371748, 0.601501, -0.707107}, {-0.213023, 0.792649, -0.571252}, {-0.346153, 0.783452, -0.516122}, {-0.46843, 0.757935, -0.453991}, {-0.757935, 0.453991, -0.46843}, {- 0.783452, 0.516122, -0.346153}, {-0.601501, 0.707107, -0.371748}, {-0.70231, 0.647412, -0.296005}, {-0.792649, 0.571252, -0.213023}, {-0.513375, 0.564254, -0.646578}, {-0.564254, 0.646578 , -0.513375}, {-0.646578, 0.513375, -0.564254}, {-0.571252, -0.213023, 0.792649}, {-0.453991, -0.46843, 0.757935}, {-0.516122, -0.346153, 0.783452}, {-0.647412, -0.296005, 0.70231}, {- 0.707107, -0.371748, 0.601501}, {-0.296005, -0.70231, 0.647412}, {-0.371748, -0.601501, 0.707107}, {-0.213023, -0.792649, 0.571252}, {-0.346153, -0.783452, 0.516122}, {-0.46843, -0.757935 , 0.453991}, {-0.757935, -0.453991, 0.46843}, {-0.783452, -0.516122, 0.346153}, {-0.601501, -0.707107, 0.371748}, {-0.70231, -0.647412, 0.296005}, {-0.792649, -0.571252, 0.213023}, {- 0.513375, -0.564254, 0.646578}, {-0.564254, -0.646578, 0.513375}, {-0.646578, -0.513375, 0.564254}, {-0.571252, -0.213023, -0.792649}, {-0.707107, -0.371748, -0.601501}, {-0.647412, -0.296005 , -0.70231}, {-0.516122, -0.346153, -0.783452}, {-0.453991, -0.46843, -0.757935}, {-0.783452, -0.516122, -0.346153}, {-0.757935, -0.453991, -0.46843}, {-0.792649, -0.571252, -0.213023}, {-0.70231, -0.647412, -0.296005}, {-0.601501, -0.707107, -0.371748}, {-0.371748, -0.601501, -0.707107}, {-0.296005, -0.70231, -0.647412}, {-0.46843, -0.757935, -0.453991}, {-0.346153 , -0.783452, -0.516122}, {-0.213023, -0.792649, -0.571252}, {-0.646578, -0.513375, -0.564254}, {-0.564254, -0.646578, -0.513375}, {-0.513375, -0.564254, -0.646578}, {0.465658, 0, 0.884965 }, {0.445365, 0.0658169, 0.892927}, {0.506298, 0.0657576, 0.859848}, {0.339123, 0, 0.940742}, {0.316778, 0.0660424, 0.946198}, {0.381722, 0.0659884, 0.921919}, {0.422364, 0.131749 , 0.896801}, {0.397351, 0.196412, 0.896401}, {0.460267, 0.196015, 0.865871}, {0.206103, 0, 0.97853}, {0.179596, 0.0666044, 0.981483}, {0.247326, 0.0665669, 0.966643}, {0.0691416, 0, 0.997607}, {0.0412484, 0.0667413, 0.996917}, {0.110385, 0.0667094, 0.991648}, {0.151549, 0.133256, 0.979426}, {0.122729, 0.19858, 0.97237}, {0.19178, 0.198337, 0.961188}, {0.368518 , 0.262661, 0.891742}, {0.339209, 0.324864, 0.882837}, {0.405434, 0.322525, 0.855337}, {0.232455, 0.264151, 0.93605}, {0.201189, 0.32553, 0.92388}, {0.270627, 0.325929, 0.905832}, { 0.307659, 0.385906, 0.869725}, {0.274694, 0.444464, 0.85264}, {0.342848, 0.442867, 0.828447}, {0.289929, 0.13257, 0.947822}, {0.26155, 0.199094, 0.944433}, {0.330607, 0.198387, 0.922682}, {-0.0691416, 8.4674e-18, 0.997607}, {-0.110385, 0.0667094, 0.991648}, {-0.0412484, 0.0667413, 0.996917}, {-0.206103, 2.52403e-17, 0.97853}, {-0.247326, 0.0665669, 0.966643}, {-0.179596 , 0.0666044, 0.981483}, {-0.151549, 0.133256, 0.979426}, {-0.19178, 0.198337, 0.961188}, {-0.122729, 0.19858, 0.97237}, {-0.339123, 4.15305e-17, 0.940742}, {-0.381722, 0.0659884, 0.921919 }, {-0.316778, 0.0660424, 0.946198}, {-0.465658, 5.70266e-17, 0.884965}, {-0.506298, 0.0657576, 0.859848}, {-0.445365, 0.0658169, 0.892927}, {-0.422364, 0.131749, 0.896801}, {-0.460267 , 0.196015, 0.865871}, {-0.397351, 0.196412, 0.896401}, {-0.232455, 0.264151, 0.93605}, {-0.270627, 0.325929, 0.905832}, {-0.201189, 0.32553, 0.92388}, {-0.368518, 0.262661, 0.891742}, {-0.405434, 0.322525, 0.855337}, {-0.339209, 0.324864, 0.882837}, {-0.307659, 0.385906, 0.869725}, {-0.342848, 0.442867, 0.828447}, {-0.274694, 0.444464, 0.85264}, {-0.289929, 0.13257 , 0.947822}, {-0.330607, 0.198387, 0.922682}, {-0.26155, 0.199094, 0.944433}, {0.233445, 0.511205, 0.827147}, {0.197274, 0.564513, 0.801504}, {0.273707, 0.55474, 0.785715}, {0.0784591 , 0.52411, 0.848029}, {0.0406752, 0.574458, 0.817523}, {0.119078, 0.57114, 0.812169}, {0.159613, 0.615456, 0.771841}, {0.121193, 0.662842, 0.738886}, {0.199331, 0.656006, 0.727958}, {- 0.0784591, 0.52411, 0.848029}, {-0.119078, 0.57114, 0.812169}, {-0.0406752, 0.574458, 0.817523}, {-0.233445, 0.511205, 0.827147}, {-0.273707, 0.55474, 0.785715}, {-0.197274, 0.564513, 0.801504 }, {-0.159613, 0.615456, 0.771841}, {-0.199331, 0.656006, 0.727958}, {-0.121193, 0.662842, 0.738886}, {0.080573, 0.708969, 0.700622}, {0.0406421, 0.749387, 0.660884}, {0.121144, 0.744727 , 0.656282}, {-0.080573, 0.708969, 0.700622}, {-0.121144, 0.744727, 0.656282}, {-0.0406421, 0.749387, 0.660884}, {-1.26468e-16, 0.786433, 0.617676}, {-0.0406404, 0.819207, 0.572056}, {0.0406404, 0.819207, 0.572056}, {-1.00072e-16, 0.622292, 0.782786}, {-0.0406771, 0.667502, 0.743496}, {0.0406771, 0.667502, 0.743496}, {-2.14722e-17, 0.133523, 0.991046}, {-0.0815011 , 0.265518, 0.960655}, {-0.0412509, 0.200368, 0.978852}, {0.0412509, 0.200368, 0.978852}, {0.0815011, 0.265518, 0.960655}, {-0.161006, 0.394136, 0.904839}, {-0.1228, 0.332342, 0.93513}, {-0.198227, 0.454262, 0.868534}, {-0.119755, 0.460882, 0.879345}, {-0.0412992, 0.464213, 0.88476}, {0.1228, 0.332342, 0.93513}, {0.161006, 0.394136, 0.904839}, {0.0412992, 0.464213, 0.88476}, {0.119755, 0.460882, 0.879345}, {0.198227, 0.454262, 0.868534}, {-0.041302, 0.33414, 0.941618}, {-6.44806e-17, 0.400968, 0.916092}, {0.041302, 0.33414, 0.941618}, {0.506298 , -0.0657576, 0.859848}, {0.445365, -0.0658169, 0.892927}, {0.460267, -0.196015, 0.865871}, {0.397351, -0.196412, 0.896401}, {0.422364, -0.131749, 0.896801}, {0.381722, -0.0659884, 0.921919 }, {0.316778, -0.0660424, 0.946198}, {0.405434, -0.322525, 0.855337}, {0.339209, -0.324864, 0.882837}, {0.368518, -0.262661, 0.891742}, {0.342848, -0.442867, 0.828447}, {0.274694, - 0.444464, 0.85264}, {0.307659, -0.385906, 0.869725}, {0.270627, -0.325929, 0.905832}, {0.201189, -0.32553, 0.92388}, {0.232455, -0.264151, 0.93605}, {0.247326, -0.0665669, 0.966643}, {0.179596, -0.0666044, 0.981483}, {0.19178, -0.198337, 0.961188}, {0.122729, -0.19858, 0.97237}, {0.151549, -0.133256, 0.979426}, {0.110385, -0.0667094, 0.991648}, {0.0412484, -0.0667413 , 0.996917}, {0.330607, -0.198387, 0.922682}, {0.26155, -0.199094, 0.944433}, {0.289929, -0.13257, 0.947822}, {0.273707, -0.55474, 0.785715}, {0.197274, -0.564513, 0.801504}, {0.233445 , -0.511205, 0.827147}, {0.199331, -0.656006, 0.727958}, {0.121193, -0.662842, 0.738886}, {0.159613, -0.615456, 0.771841}, {0.119078, -0.57114, 0.812169}, {0.0406752, -0.574458, 0.817523 }, {0.0784591, -0.52411, 0.848029}, {0.121144, -0.744727, 0.656282}, {0.0406421, -0.749387, 0.660884}, {0.080573, -0.708969, 0.700622}, {0.0406404, -0.819207, 0.572056}, {-0.0406404 , -0.819207, 0.572056}, {-1.26468e-16, -0.786433, 0.617676}, {-0.0406421, -0.749387, 0.660884}, {-0.121144, -0.744727, 0.656282}, {-0.080573, -0.708969, 0.700622}, {-0.0406752, -0.574458 , 0.817523}, {-0.119078, -0.57114, 0.812169}, {-0.0784591, -0.52411, 0.848029}, {-0.121193, -0.662842, 0.738886}, {-0.199331, -0.656006, 0.727958}, {-0.159613, -0.615456, 0.771841}, {- 0.197274, -0.564513, 0.801504}, {-0.273707, -0.55474, 0.785715}, {-0.233445, -0.511205, 0.827147}, {0.0406771, -0.667502, 0.743496}, {-0.0406771, -0.667502, 0.743496}, {-1.00072e-16, -0.622292 , 0.782786}, {-0.0412484, -0.0667413, 0.996917}, {-0.110385, -0.0667094, 0.991648}, {-0.122729, -0.19858, 0.97237}, {-0.19178, -0.198337, 0.961188}, {-0.151549, -0.133256, 0.979426}, {-0.179596, -0.0666044, 0.981483}, {-0.247326, -0.0665669, 0.966643}, {-0.201189, -0.32553, 0.92388}, {-0.270627, -0.325929, 0.905832}, {-0.232455, -0.264151, 0.93605}, {-0.274694, - 0.444464, 0.85264}, {-0.342848, -0.442867, 0.828447}, {-0.307659, -0.385906, 0.869725}, {-0.339209, -0.324864, 0.882837}, {-0.405434, -0.322525, 0.855337}, {-0.368518, -0.262661, 0.891742 }, {-0.316778, -0.0660424, 0.946198}, {-0.381722, -0.0659884, 0.921919}, {-0.397351, -0.196412, 0.896401}, {-0.460267, -0.196015, 0.865871}, {-0.422364, -0.131749, 0.896801}, {-0.445365 , -0.0658169, 0.892927}, {-0.506298, -0.0657576, 0.859848}, {-0.26155, -0.199094, 0.944433}, {-0.330607, -0.198387, 0.922682}, {-0.289929, -0.13257, 0.947822}, {0.198227, -0.454262, 0.868534 }, {0.0412992, -0.464213, 0.88476}, {0.119755, -0.460882, 0.879345}, {0.161006, -0.394136, 0.904839}, {0.1228, -0.332342, 0.93513}, {-0.119755, -0.460882, 0.879345}, {-0.0412992, - 0.464213, 0.88476}, {-0.198227, -0.454262, 0.868534}, {-0.161006, -0.394136, 0.904839}, {-0.1228, -0.332342, 0.93513}, {0.0815011, -0.265518, 0.960655}, {0.0412509, -0.200368, 0.978852}, {-0.0815011, -0.265518, 0.960655}, {-0.0412509, -0.200368, 0.978852}, {-2.14722e-17, -0.133523, 0.991046}, {-6.44806e-17, -0.400968, 0.916092}, {-0.041302, -0.33414, 0.941618}, { 0.041302, -0.33414, 0.941618}, {0.506298, 0.0657576, -0.859848}, {0.445365, 0.0658169, -0.892927}, {0.465658, 0, -0.884965}, {0.460267, 0.196015, -0.865871}, {0.397351, 0.196412, -0.896401 }, {0.422364, 0.131749, -0.896801}, {0.381722, 0.0659884, -0.921919}, {0.316778, 0.0660424, -0.946198}, {0.339123, 0, -0.940742}, {0.405434, 0.322525, -0.855337}, {0.339209, 0.324864 , -0.882837}, {0.368518, 0.262661, -0.891742}, {0.342848, 0.442867, -0.828447}, {0.274694, 0.444464, -0.85264}, {0.307659, 0.385906, -0.869725}, {0.270627, 0.325929, -0.905832}, { 0.201189, 0.32553, -0.92388}, {0.232455, 0.264151, -0.93605}, {0.247326, 0.0665669, -0.966643}, {0.179596, 0.0666044, -0.981483}, {0.206103, 0, -0.97853}, {0.19178, 0.198337, -0.961188}, {0.122729, 0.19858, -0.97237}, {0.151549, 0.133256, -0.979426}, {0.110385, 0.0667094, -0.991648}, {0.0412484, 0.0667413, -0.996917}, {0.0691416, 0, -0.997607}, {0.330607, 0.198387 , -0.922682}, {0.26155, 0.199094, -0.944433}, {0.289929, 0.13257, -0.947822}, {0.273707, 0.55474, -0.785715}, {0.197274, 0.564513, -0.801504}, {0.233445, 0.511205, -0.827147}, {0.199331 , 0.656006, -0.727958}, {0.121193, 0.662842, -0.738886}, {0.159613, 0.615456, -0.771841}, {0.119078, 0.57114, -0.812169}, {0.0406752, 0.574458, -0.817523}, {0.0784591, 0.52411, -0.848029 }, {0.121144, 0.744727, -0.656282}, {0.0406421, 0.749387, -0.660884}, {0.080573, 0.708969, -0.700622}, {0.0406404, 0.819207, -0.572056}, {-0.0406404, 0.819207, -0.572056}, {-1.26468e-16 , 0.786433, -0.617676}, {-0.0406421, 0.749387, -0.660884}, {-0.121144, 0.744727, -0.656282}, {-0.080573, 0.708969, -0.700622}, {-0.0406752, 0.574458, -0.817523}, {-0.119078, 0.57114, -0.812169 }, {-0.0784591, 0.52411, -0.848029}, {-0.121193, 0.662842, -0.738886}, {-0.199331, 0.656006, -0.727958}, {-0.159613, 0.615456, -0.771841}, {-0.197274, 0.564513, -0.801504}, {-0.273707 , 0.55474, -0.785715}, {-0.233445, 0.511205, -0.827147}, {0.0406771, 0.667502, -0.743496}, {-0.0406771, 0.667502, -0.743496}, {-1.00072e-16, 0.622292, -0.782786}, {-0.0412484, 0.0667413, - 0.996917}, {-0.110385, 0.0667094, -0.991648}, {-0.0691416, 8.4674e-18, -0.997607}, {-0.122729, 0.19858, -0.97237}, {-0.19178, 0.198337, -0.961188}, {-0.151549, 0.133256, -0.979426}, {- 0.179596, 0.0666044, -0.981483}, {-0.247326, 0.0665669, -0.966643}, {-0.206103, 2.52403e-17, -0.97853}, {-0.201189, 0.32553, -0.92388}, {-0.270627, 0.325929, -0.905832}, {-0.232455, 0.264151 , -0.93605}, {-0.274694, 0.444464, -0.85264}, {-0.342848, 0.442867, -0.828447}, {-0.307659, 0.385906, -0.869725}, {-0.339209, 0.324864, -0.882837}, {-0.405434, 0.322525, -0.855337}, {- 0.368518, 0.262661, -0.891742}, {-0.316778, 0.0660424, -0.946198}, {-0.381722, 0.0659884, -0.921919}, {-0.339123, 4.15305e-17, -0.940742}, {-0.397351, 0.196412, -0.896401}, {-0.460267, 0.196015 , -0.865871}, {-0.422364, 0.131749, -0.896801}, {-0.445365, 0.0658169, -0.892927}, {-0.506298, 0.0657576, -0.859848}, {-0.465658, 5.70266e-17, -0.884965}, {-0.26155, 0.199094, -0.944433}, {-0.330607, 0.198387, -0.922682}, {-0.289929, 0.13257, -0.947822}, {0.198227, 0.454262, -0.868534}, {0.0412992, 0.464213, -0.88476}, {0.119755, 0.460882, -0.879345}, {0.161006, 0.394136 , -0.904839}, {0.1228, 0.332342, -0.93513}, {-0.119755, 0.460882, -0.879345}, {-0.0412992, 0.464213, -0.88476}, {-0.198227, 0.454262, -0.868534}, {-0.161006, 0.394136, -0.904839}, {- 0.1228, 0.332342, -0.93513}, {0.0815011, 0.265518, -0.960655}, {0.0412509, 0.200368, -0.978852}, {-0.0815011, 0.265518, -0.960655}, {-0.0412509, 0.200368, -0.978852}, {3.78241e-17, 0.133523 , -0.991046}, {-6.44806e-17, 0.400968, -0.916092}, {-0.041302, 0.33414, -0.941618}, {0.041302, 0.33414, -0.941618}, {0.445365, -0.0658169, -0.892927}, {0.506298, -0.0657576, -0.859848}, {0.316778, -0.0660424, -0.946198}, {0.381722, -0.0659884, -0.921919}, {0.422364, -0.131749, -0.896801}, {0.397351, -0.196412, -0.896401}, {0.460267, -0.196015, -0.865871}, {0.179596, - 0.0666044, -0.981483}, {0.247326, -0.0665669, -0.966643}, {0.0412484, -0.0667413, -0.996917}, {0.110385, -0.0667094, -0.991648}, {0.151549, -0.133256, -0.979426}, {0.122729, -0.19858, -0.97237 }, {0.19178, -0.198337, -0.961188}, {0.368518, -0.262661, -0.891742}, {0.339209, -0.324864, -0.882837}, {0.405434, -0.322525, -0.855337}, {0.232455, -0.264151, -0.93605}, {0.201189 , -0.32553, -0.92388}, {0.270627, -0.325929, -0.905832}, {0.307659, -0.385906, -0.869725}, {0.274694, -0.444464, -0.85264}, {0.342848, -0.442867, -0.828447}, {0.289929, -0.13257, -0.947822 }, {0.26155, -0.199094, -0.944433}, {0.330607, -0.198387, -0.922682}, {-0.110385, -0.0667094, -0.991648}, {-0.0412484, -0.0667413, -0.996917}, {-0.247326, -0.0665669, -0.966643}, {- 0.179596, -0.0666044, -0.981483}, {-0.151549, -0.133256, -0.979426}, {-0.19178, -0.198337, -0.961188}, {-0.122729, -0.19858, -0.97237}, {-0.381722, -0.0659884, -0.921919}, {-0.316778, -0.0660424 , -0.946198}, {-0.506298, -0.0657576, -0.859848}, {-0.445365, -0.0658169, -0.892927}, {-0.422364, -0.131749, -0.896801}, {-0.460267, -0.196015, -0.865871}, {-0.397351, -0.196412, -0.896401 }, {-0.232455, -0.264151, -0.93605}, {-0.270627, -0.325929, -0.905832}, {-0.201189, -0.32553, -0.92388}, {-0.368518, -0.262661, -0.891742}, {-0.405434, -0.322525, -0.855337}, {-0.339209 , -0.324864, -0.882837}, {-0.307659, -0.385906, -0.869725}, {-0.342848, -0.442867, -0.828447}, {-0.274694, -0.444464, -0.85264}, {-0.289929, -0.13257, -0.947822}, {-0.330607, -0.198387, - 0.922682}, {-0.26155, -0.199094, -0.944433}, {0.233445, -0.511205, -0.827147}, {0.197274, -0.564513, -0.801504}, {0.273707, -0.55474, -0.785715}, {0.0784591, -0.52411, -0.848029}, { 0.0406752, -0.574458, -0.817523}, {0.119078, -0.57114, -0.812169}, {0.159613, -0.615456, -0.771841}, {0.121193, -0.662842, -0.738886}, {0.199331, -0.656006, -0.727958}, {-0.0784591, -0.52411 , -0.848029}, {-0.119078, -0.57114, -0.812169}, {-0.0406752, -0.574458, -0.817523}, {-0.233445, -0.511205, -0.827147}, {-0.273707, -0.55474, -0.785715}, {-0.197274, -0.564513, -0.801504}, {-0.159613, -0.615456, -0.771841}, {-0.199331, -0.656006, -0.727958}, {-0.121193, -0.662842, -0.738886}, {0.080573, -0.708969, -0.700622}, {0.0406421, -0.749387, -0.660884}, {0.121144 , -0.744727, -0.656282}, {-0.080573, -0.708969, -0.700622}, {-0.121144, -0.744727, -0.656282}, {-0.0406421, -0.749387, -0.660884}, {-1.26468e-16, -0.786433, -0.617676}, {-0.0406404, -0.819207 , -0.572056}, {0.0406404, -0.819207, -0.572056}, {-1.00072e-16, -0.622292, -0.782786}, {-0.0406771, -0.667502, -0.743496}, {0.0406771, -0.667502, -0.743496}, {3.78241e-17, -0.133523, -0.991046 }, {-0.0815011, -0.265518, -0.960655}, {-0.0412509, -0.200368, -0.978852}, {0.0412509, -0.200368, -0.978852}, {0.0815011, -0.265518, -0.960655}, {-0.161006, -0.394136, -0.904839}, {- 0.1228, -0.332342, -0.93513}, {-0.198227, -0.454262, -0.868534}, {-0.119755, -0.460882, -0.879345}, {-0.0412992, -0.464213, -0.88476}, {0.1228, -0.332342, -0.93513}, {0.161006, -0.394136 , -0.904839}, {0.0412992, -0.464213, -0.88476}, {0.119755, -0.460882, -0.879345}, {0.198227, -0.454262, -0.868534}, {-0.041302, -0.33414, -0.941618}, {-6.44806e-17, -0.400968, -0.916092}, {0.041302, -0.33414, -0.941618}, {0.884965, 0.465658, 6.12323e-17}, {0.892927, 0.445365, 0.0658169}, {0.859848, 0.506298, 0.0657576}, {0.940742, 0.339123, 6.12323e-17}, {0.946198 , 0.316778, 0.0660424}, {0.921919, 0.381722, 0.0659884}, {0.896801, 0.422364, 0.131749}, {0.896401, 0.397351, 0.196412}, {0.865871, 0.460267, 0.196015}, {0.97853, 0.206103, 6.12323e-17}, {0.981483, 0.179596, 0.0666044}, {0.966643, 0.247326, 0.0665669}, {0.997607, 0.0691416, 6.12323e-17}, {0.996917, 0.0412484, 0.0667413}, {0.991648, 0.110385, 0.0667094}, {0.979426 , 0.151549, 0.133256}, {0.97237, 0.122729, 0.19858}, {0.961188, 0.19178, 0.198337}, {0.891742, 0.368518, 0.262661}, {0.882837, 0.339209, 0.324864}, {0.855337, 0.405434, 0.322525}, { 0.93605, 0.232455, 0.264151}, {0.92388, 0.201189, 0.32553}, {0.905832, 0.270627, 0.325929}, {0.869725, 0.307659, 0.385906}, {0.85264, 0.274694, 0.444464}, {0.828447, 0.342848, 0.442867}, {0.947822, 0.289929, 0.13257}, {0.944433, 0.26155, 0.199094}, {0.922682, 0.330607, 0.198387}, {0.997607, -0.0691416, 6.12323e-17}, {0.991648, -0.110385, 0.0667094}, {0.996917, -0.0412484 , 0.0667413}, {0.97853, -0.206103, 6.12323e-17}, {0.966643, -0.247326, 0.0665669}, {0.981483, -0.179596, 0.0666044}, {0.979426, -0.151549, 0.133256}, {0.961188, -0.19178, 0.198337}, { 0.97237, -0.122729, 0.19858}, {0.940742, -0.339123, 6.12323e-17}, {0.921919, -0.381722, 0.0659884}, {0.946198, -0.316778, 0.0660424}, {0.884965, -0.465658, 6.12323e-17}, {0.859848, -0.506298 , 0.0657576}, {0.892927, -0.445365, 0.0658169}, {0.896801, -0.422364, 0.131749}, {0.865871, -0.460267, 0.196015}, {0.896401, -0.397351, 0.196412}, {0.93605, -0.232455, 0.264151}, { 0.905832, -0.270627, 0.325929}, {0.92388, -0.201189, 0.32553}, {0.891742, -0.368518, 0.262661}, {0.855337, -0.405434, 0.322525}, {0.882837, -0.339209, 0.324864}, {0.869725, -0.307659, 0.385906 }, {0.828447, -0.342848, 0.442867}, {0.85264, -0.274694, 0.444464}, {0.947822, -0.289929, 0.13257}, {0.922682, -0.330607, 0.198387}, {0.944433, -0.26155, 0.199094}, {0.827147, 0.233445 , 0.511205}, {0.801504, 0.197274, 0.564513}, {0.785715, 0.273707, 0.55474}, {0.848029, 0.0784591, 0.52411}, {0.817523, 0.0406752, 0.574458}, {0.812169, 0.119078, 0.57114}, {0.771841 , 0.159613, 0.615456}, {0.738886, 0.121193, 0.662842}, {0.727958, 0.199331, 0.656006}, {0.848029, -0.0784591, 0.52411}, {0.812169, -0.119078, 0.57114}, {0.817523, -0.0406752, 0.574458}, {0.827147, -0.233445, 0.511205}, {0.785715, -0.273707, 0.55474}, {0.801504, -0.197274, 0.564513}, {0.771841, -0.159613, 0.615456}, {0.727958, -0.199331, 0.656006}, {0.738886, -0.121193 , 0.662842}, {0.700622, 0.080573, 0.708969}, {0.660884, 0.0406421, 0.749387}, {0.656282, 0.121144, 0.744727}, {0.700622, -0.080573, 0.708969}, {0.656282, -0.121144, 0.744727}, {0.660884 , -0.0406421, 0.749387}, {0.617676, 0, 0.786433}, {0.572056, -0.0406404, 0.819207}, {0.572056, 0.0406404, 0.819207}, {0.782786, 0, 0.622292}, {0.743496, -0.0406771, 0.667502}, {0.743496 , 0.0406771, 0.667502}, {0.991046, 0, 0.133523}, {0.960655, -0.0815011, 0.265518}, {0.978852, -0.0412509, 0.200368}, {0.978852, 0.0412509, 0.200368}, {0.960655, 0.0815011, 0.265518}, {0.904839, -0.161006, 0.394136}, {0.93513, -0.1228, 0.332342}, {0.868534, -0.198227, 0.454262}, {0.879345, -0.119755, 0.460882}, {0.88476, -0.0412992, 0.464213}, {0.93513, 0.1228, 0.332342 }, {0.904839, 0.161006, 0.394136}, {0.88476, 0.0412992, 0.464213}, {0.879345, 0.119755, 0.460882}, {0.868534, 0.198227, 0.454262}, {0.941618, -0.041302, 0.33414}, {0.916092, 0, 0.400968 }, {0.941618, 0.041302, 0.33414}, {0.859848, 0.506298, -0.0657576}, {0.892927, 0.445365, -0.0658169}, {0.865871, 0.460267, -0.196015}, {0.896401, 0.397351, -0.196412}, {0.896801, 0.422364, -0.131749}, {0.921919, 0.381722, -0.0659884}, {0.946198, 0.316778, -0.0660424}, {0.855337, 0.405434, -0.322525}, {0.882837, 0.339209, -0.324864}, {0.891742, 0.368518, -0.262661 }, {0.828447, 0.342848, -0.442867}, {0.85264, 0.274694, -0.444464}, {0.869725, 0.307659, -0.385906}, {0.905832, 0.270627, -0.325929}, {0.92388, 0.201189, -0.32553}, {0.93605, 0.232455 , -0.264151}, {0.966643, 0.247326, -0.0665669}, {0.981483, 0.179596, -0.0666044}, {0.961188, 0.19178, -0.198337}, {0.97237, 0.122729, -0.19858}, {0.979426, 0.151549, -0.133256}, { 0.991648, 0.110385, -0.0667094}, {0.996917, 0.0412484, -0.0667413}, {0.922682, 0.330607, -0.198387}, {0.944433, 0.26155, -0.199094}, {0.947822, 0.289929, -0.13257}, {0.785715, 0.273707, - 0.55474}, {0.801504, 0.197274, -0.564513}, {0.827147, 0.233445, -0.511205}, {0.727958, 0.199331, -0.656006}, {0.738886, 0.121193, -0.662842}, {0.771841, 0.159613, -0.615456}, {0.812169 , 0.119078, -0.57114}, {0.817523, 0.0406752, -0.574458}, {0.848029, 0.0784591, -0.52411}, {0.656282, 0.121144, -0.744727}, {0.660884, 0.0406421, -0.749387}, {0.700622, 0.080573, -0.708969 }, {0.572056, 0.0406404, -0.819207}, {0.572056, -0.0406404, -0.819207}, {0.617676, 0, -0.786433}, {0.660884, -0.0406421, -0.749387}, {0.656282, -0.121144, -0.744727}, {0.700622, - 0.080573, -0.708969}, {0.817523, -0.0406752, -0.574458}, {0.812169, -0.119078, -0.57114}, {0.848029, -0.0784591, -0.52411}, {0.738886, -0.121193, -0.662842}, {0.727958, -0.199331, -0.656006 }, {0.771841, -0.159613, -0.615456}, {0.801504, -0.197274, -0.564513}, {0.785715, -0.273707, -0.55474}, {0.827147, -0.233445, -0.511205}, {0.743496, 0.0406771, -0.667502}, {0.743496 , -0.0406771, -0.667502}, {0.782786, 0, -0.622292}, {0.996917, -0.0412484, -0.0667413}, {0.991648, -0.110385, -0.0667094}, {0.97237, -0.122729, -0.19858}, {0.961188, -0.19178, -0.198337}, {0.979426, -0.151549, -0.133256}, {0.981483, -0.179596, -0.0666044}, {0.966643, -0.247326, -0.0665669}, {0.92388, -0.201189, -0.32553}, {0.905832, -0.270627, -0.325929}, {0.93605 , -0.232455, -0.264151}, {0.85264, -0.274694, -0.444464}, {0.828447, -0.342848, -0.442867}, {0.869725, -0.307659, -0.385906}, {0.882837, -0.339209, -0.324864}, {0.855337, -0.405434, -0.322525 }, {0.891742, -0.368518, -0.262661}, {0.946198, -0.316778, -0.0660424}, {0.921919, -0.381722, -0.0659884}, {0.896401, -0.397351, -0.196412}, {0.865871, -0.460267, -0.196015}, {0.896801 , -0.422364, -0.131749}, {0.892927, -0.445365, -0.0658169}, {0.859848, -0.506298, -0.0657576}, {0.944433, -0.26155, -0.199094}, {0.922682, -0.330607, -0.198387}, {0.947822, -0.289929, -0.13257 }, {0.868534, 0.198227, -0.454262}, {0.88476, 0.0412992, -0.464213}, {0.879345, 0.119755, -0.460882}, {0.904839, 0.161006, -0.394136}, {0.93513, 0.1228, -0.332342}, {0.879345, -0.119755 , -0.460882}, {0.88476, -0.0412992, -0.464213}, {0.868534, -0.198227, -0.454262}, {0.904839, -0.161006, -0.394136}, {0.93513, -0.1228, -0.332342}, {0.960655, 0.0815011, -0.265518}, { 0.978852, 0.0412509, -0.200368}, {0.960655, -0.0815011, -0.265518}, {0.978852, -0.0412509, -0.200368}, {0.991046, 0, -0.133523}, {0.916092, 0, -0.400968}, {0.941618, -0.041302, -0.33414}, {0.941618, 0.041302, -0.33414}, {-0.884965, -0.465658, 6.12323e-17}, {-0.892927, -0.445365, 0.0658169}, {-0.859848, -0.506298, 0.0657576}, {-0.940742, -0.339123, 6.12323e-17}, {- 0.946198, -0.316778, 0.0660424}, {-0.921919, -0.381722, 0.0659884}, {-0.896801, -0.422364, 0.131749}, {-0.896401, -0.397351, 0.196412}, {-0.865871, -0.460267, 0.196015}, {-0.97853, -0.206103 , 6.12323e-17}, {-0.981483, -0.179596, 0.0666044}, {-0.966643, -0.247326, 0.0665669}, {-0.997607, -0.0691416, 6.12323e-17}, {-0.996917, -0.0412484, 0.0667413}, {-0.991648, -0.110385, 0.0667094 }, {-0.979426, -0.151549, 0.133256}, {-0.97237, -0.122729, 0.19858}, {-0.961188, -0.19178, 0.198337}, {-0.891742, -0.368518, 0.262661}, {-0.882837, -0.339209, 0.324864}, {-0.855337 , -0.405434, 0.322525}, {-0.93605, -0.232455, 0.264151}, {-0.92388, -0.201189, 0.32553}, {-0.905832, -0.270627, 0.325929}, {-0.869725, -0.307659, 0.385906}, {-0.85264, -0.274694, 0.444464 }, {-0.828447, -0.342848, 0.442867}, {-0.947822, -0.289929, 0.13257}, {-0.944433, -0.26155, 0.199094}, {-0.922682, -0.330607, 0.198387}, {-0.997607, 0.0691416, 6.12323e-17}, {-0.991648 , 0.110385, 0.0667094}, {-0.996917, 0.0412484, 0.0667413}, {-0.97853, 0.206103, 6.12323e-17}, {-0.966643, 0.247326, 0.0665669}, {-0.981483, 0.179596, 0.0666044}, {-0.979426, 0.151549, 0.133256 }, {-0.961188, 0.19178, 0.198337}, {-0.97237, 0.122729, 0.19858}, {-0.940742, 0.339123, 6.12323e-17}, {-0.921919, 0.381722, 0.0659884}, {-0.946198, 0.316778, 0.0660424}, {-0.884965 , 0.465658, 6.12323e-17}, {-0.859848, 0.506298, 0.0657576}, {-0.892927, 0.445365, 0.0658169}, {-0.896801, 0.422364, 0.131749}, {-0.865871, 0.460267, 0.196015}, {-0.896401, 0.397351, 0.196412 }, {-0.93605, 0.232455, 0.264151}, {-0.905832, 0.270627, 0.325929}, {-0.92388, 0.201189, 0.32553}, {-0.891742, 0.368518, 0.262661}, {-0.855337, 0.405434, 0.322525}, {-0.882837, 0.339209 , 0.324864}, {-0.869725, 0.307659, 0.385906}, {-0.828447, 0.342848, 0.442867}, {-0.85264, 0.274694, 0.444464}, {-0.947822, 0.289929, 0.13257}, {-0.922682, 0.330607, 0.198387}, {-0.944433 , 0.26155, 0.199094}, {-0.827147, -0.233445, 0.511205}, {-0.801504, -0.197274, 0.564513}, {-0.785715, -0.273707, 0.55474}, {-0.848029, -0.0784591, 0.52411}, {-0.817523, -0.0406752, 0.574458 }, {-0.812169, -0.119078, 0.57114}, {-0.771841, -0.159613, 0.615456}, {-0.738886, -0.121193, 0.662842}, {-0.727958, -0.199331, 0.656006}, {-0.848029, 0.0784591, 0.52411}, {-0.812169 , 0.119078, 0.57114}, {-0.817523, 0.0406752, 0.574458}, {-0.827147, 0.233445, 0.511205}, {-0.785715, 0.273707, 0.55474}, {-0.801504, 0.197274, 0.564513}, {-0.771841, 0.159613, 0.615456}, {-0.727958, 0.199331, 0.656006}, {-0.738886, 0.121193, 0.662842}, {-0.700622, -0.080573, 0.708969}, {-0.660884, -0.0406421, 0.749387}, {-0.656282, -0.121144, 0.744727}, {-0.700622 , 0.080573, 0.708969}, {-0.656282, 0.121144, 0.744727}, {-0.660884, 0.0406421, 0.749387}, {-0.617676, 7.56435e-17, 0.786433}, {-0.572056, 0.0406404, 0.819207}, {-0.572056, -0.0406404, 0.819207 }, {-0.782786, 9.58636e-17, 0.622292}, {-0.743496, 0.0406771, 0.667502}, {-0.743496, -0.0406771, 0.667502}, {-0.991046, 1.21368e-16, 0.133523}, {-0.960655, 0.0815011, 0.265518}, {- 0.978852, 0.0412509, 0.200368}, {-0.978852, -0.0412509, 0.200368}, {-0.960655, -0.0815011, 0.265518}, {-0.904839, 0.161006, 0.394136}, {-0.93513, 0.1228, 0.332342}, {-0.868534, 0.198227, 0.454262}, {-0.879345, 0.119755, 0.460882}, {-0.88476, 0.0412992, 0.464213}, {-0.93513, -0.1228, 0.332342}, {-0.904839, -0.161006, 0.394136}, {-0.88476, -0.0412992, 0.464213}, {-0.879345 , -0.119755, 0.460882}, {-0.868534, -0.198227, 0.454262}, {-0.941618, 0.041302, 0.33414}, {-0.916092, 1.12189e-16, 0.400968}, {-0.941618, -0.041302, 0.33414}, {-0.859848, -0.506298, -0.0657576 }, {-0.892927, -0.445365, -0.0658169}, {-0.865871, -0.460267, -0.196015}, {-0.896401, -0.397351, -0.196412}, {-0.896801, -0.422364, -0.131749}, {-0.921919, -0.381722, -0.0659884}, {- 0.946198, -0.316778, -0.0660424}, {-0.855337, -0.405434, -0.322525}, {-0.882837, -0.339209, -0.324864}, {-0.891742, -0.368518, -0.262661}, {-0.828447, -0.342848, -0.442867}, {-0.85264, - 0.274694, -0.444464}, {-0.869725, -0.307659, -0.385906}, {-0.905832, -0.270627, -0.325929}, {-0.92388, -0.201189, -0.32553}, {-0.93605, -0.232455, -0.264151}, {-0.966643, -0.247326, -0.0665669 }, {-0.981483, -0.179596, -0.0666044}, {-0.961188, -0.19178, -0.198337}, {-0.97237, -0.122729, -0.19858}, {-0.979426, -0.151549, -0.133256}, {-0.991648, -0.110385, -0.0667094}, {- 0.996917, -0.0412484, -0.0667413}, {-0.922682, -0.330607, -0.198387}, {-0.944433, -0.26155, -0.199094}, {-0.947822, -0.289929, -0.13257}, {-0.785715, -0.273707, -0.55474}, {-0.801504, -0.197274 , -0.564513}, {-0.827147, -0.233445, -0.511205}, {-0.727958, -0.199331, -0.656006}, {-0.738886, -0.121193, -0.662842}, {-0.771841, -0.159613, -0.615456}, {-0.812169, -0.119078, -0.57114}, {-0.817523, -0.0406752, -0.574458}, {-0.848029, -0.0784591, -0.52411}, {-0.656282, -0.121144, -0.744727}, {-0.660884, -0.0406421, -0.749387}, {-0.700622, -0.080573, -0.708969}, {- 0.572056, -0.0406404, -0.819207}, {-0.572056, 0.0406404, -0.819207}, {-0.617676, 7.56435e-17, -0.786433}, {-0.660884, 0.0406421, -0.749387}, {-0.656282, 0.121144, -0.744727}, {-0.700622, 0.080573, -0.708969}, {-0.817523, 0.0406752, -0.574458}, {-0.812169, 0.119078, -0.57114}, {-0.848029, 0.0784591, -0.52411}, {-0.738886, 0.121193, -0.662842}, {-0.727958, 0.199331, -0.656006 }, {-0.771841, 0.159613, -0.615456}, {-0.801504, 0.197274, -0.564513}, {-0.785715, 0.273707, -0.55474}, {-0.827147, 0.233445, -0.511205}, {-0.743496, -0.0406771, -0.667502}, {-0.743496 , 0.0406771, -0.667502}, {-0.782786, 9.58636e-17, -0.622292}, {-0.996917, 0.0412484, -0.0667413}, {-0.991648, 0.110385, -0.0667094}, {-0.97237, 0.122729, -0.19858}, {-0.961188, 0.19178, - 0.198337}, {-0.979426, 0.151549, -0.133256}, {-0.981483, 0.179596, -0.0666044}, {-0.966643, 0.247326, -0.0665669}, {-0.92388, 0.201189, -0.32553}, {-0.905832, 0.270627, -0.325929}, {- 0.93605, 0.232455, -0.264151}, {-0.85264, 0.274694, -0.444464}, {-0.828447, 0.342848, -0.442867}, {-0.869725, 0.307659, -0.385906}, {-0.882837, 0.339209, -0.324864}, {-0.855337, 0.405434 , -0.322525}, {-0.891742, 0.368518, -0.262661}, {-0.946198, 0.316778, -0.0660424}, {-0.921919, 0.381722, -0.0659884}, {-0.896401, 0.397351, -0.196412}, {-0.865871, 0.460267, -0.196015}, {-0.896801, 0.422364, -0.131749}, {-0.892927, 0.445365, -0.0658169}, {-0.859848, 0.506298, -0.0657576}, {-0.944433, 0.26155, -0.199094}, {-0.922682, 0.330607, -0.198387}, {-0.947822, 0.289929, -0.13257}, {-0.868534, -0.198227, -0.454262}, {-0.88476, -0.0412992, -0.464213}, {-0.879345, -0.119755, -0.460882}, {-0.904839, -0.161006, -0.394136}, {-0.93513, -0.1228, -0.332342 }, {-0.879345, 0.119755, -0.460882}, {-0.88476, 0.0412992, -0.464213}, {-0.868534, 0.198227, -0.454262}, {-0.904839, 0.161006, -0.394136}, {-0.93513, 0.1228, -0.332342}, {-0.960655 , -0.0815011, -0.265518}, {-0.978852, -0.0412509, -0.200368}, {-0.960655, 0.0815011, -0.265518}, {-0.978852, 0.0412509, -0.200368}, {-0.991046, 1.21368e-16, -0.133523}, {-0.916092, 1.12189e-16 , -0.400968}, {-0.941618, 0.041302, -0.33414}, {-0.941618, -0.041302, -0.33414}, {5.41885e-17, 0.884965, 0.465658}, {0.0658169, 0.892927, 0.445365}, {0.0657576, 0.859848, 0.506298}, { 5.76038e-17, 0.940742, 0.339123}, {0.0660424, 0.946198, 0.316778}, {0.0659884, 0.921919, 0.381722}, {0.131749, 0.896801, 0.422364}, {0.196412, 0.896401, 0.397351}, {0.196015, 0.865871, 0.460267 }, {5.99177e-17, 0.97853, 0.206103}, {0.0666044, 0.981483, 0.179596}, {0.0665669, 0.966643, 0.247326}, {6.10858e-17, 0.997607, 0.0691416}, {0.0667413, 0.996917, 0.0412484}, {0.0667094 , 0.991648, 0.110385}, {0.133256, 0.979426, 0.151549}, {0.19858, 0.97237, 0.122729}, {0.198337, 0.961188, 0.19178}, {0.262661, 0.891742, 0.368518}, {0.324864, 0.882837, 0.339209}, { 0.322525, 0.855337, 0.405434}, {0.264151, 0.93605, 0.232455}, {0.32553, 0.92388, 0.201189}, {0.325929, 0.905832, 0.270627}, {0.385906, 0.869725, 0.307659}, {0.444464, 0.85264, 0.274694}, {0.442867, 0.828447, 0.342848}, {0.13257, 0.947822, 0.289929}, {0.199094, 0.944433, 0.26155}, {0.198387, 0.922682, 0.330607}, {6.10858e-17, 0.997607, -0.0691416}, {0.0667094, 0.991648 , -0.110385}, {0.0667413, 0.996917, -0.0412484}, {5.99177e-17, 0.97853, -0.206103}, {0.0665669, 0.966643, -0.247326}, {0.0666044, 0.981483, -0.179596}, {0.133256, 0.979426, -0.151549}, {0.198337, 0.961188, -0.19178}, {0.19858, 0.97237, -0.122729}, {5.76038e-17, 0.940742, -0.339123}, {0.0659884, 0.921919, -0.381722}, {0.0660424, 0.946198, -0.316778}, {5.41885e-17, 0.884965 , -0.465658}, {0.0657576, 0.859848, -0.506298}, {0.0658169, 0.892927, -0.445365}, {0.131749, 0.896801, -0.422364}, {0.196015, 0.865871, -0.460267}, {0.196412, 0.896401, -0.397351}, { 0.264151, 0.93605, -0.232455}, {0.325929, 0.905832, -0.270627}, {0.32553, 0.92388, -0.201189}, {0.262661, 0.891742, -0.368518}, {0.322525, 0.855337, -0.405434}, {0.324864, 0.882837, -0.339209 }, {0.385906, 0.869725, -0.307659}, {0.442867, 0.828447, -0.342848}, {0.444464, 0.85264, -0.274694}, {0.13257, 0.947822, -0.289929}, {0.198387, 0.922682, -0.330607}, {0.199094, 0.944433 , -0.26155}, {0.511205, 0.827147, 0.233445}, {0.564513, 0.801504, 0.197274}, {0.55474, 0.785715, 0.273707}, {0.52411, 0.848029, 0.0784591}, {0.574458, 0.817523, 0.0406752}, {0.57114 , 0.812169, 0.119078}, {0.615456, 0.771841, 0.159613}, {0.662842, 0.738886, 0.121193}, {0.656006, 0.727958, 0.199331}, {0.52411, 0.848029, -0.0784591}, {0.57114, 0.812169, -0.119078}, {0.574458, 0.817523, -0.0406752}, {0.511205, 0.827147, -0.233445}, {0.55474, 0.785715, -0.273707}, {0.564513, 0.801504, -0.197274}, {0.615456, 0.771841, -0.159613}, {0.656006, 0.727958 , -0.199331}, {0.662842, 0.738886, -0.121193}, {0.708969, 0.700622, 0.080573}, {0.749387, 0.660884, 0.0406421}, {0.744727, 0.656282, 0.121144}, {0.708969, 0.700622, -0.080573}, {0.744727 , 0.656282, -0.121144}, {0.749387, 0.660884, -0.0406421}, {0.786433, 0.617676, -1.60812e-16}, {0.819207, 0.572056, -0.0406404}, {0.819207, 0.572056, 0.0406404}, {0.622292, 0.782786, -1.60812e-16 }, {0.667502, 0.743496, -0.0406771}, {0.667502, 0.743496, 0.0406771}, {0.133523, 0.991046, -1.60812e-16}, {0.265518, 0.960655, -0.0815011}, {0.200368, 0.978852, -0.0412509}, {0.200368 , 0.978852, 0.0412509}, {0.265518, 0.960655, 0.0815011}, {0.394136, 0.904839, -0.161006}, {0.332342, 0.93513, -0.1228}, {0.454262, 0.868534, -0.198227}, {0.460882, 0.879345, -0.119755}, {0.464213, 0.88476, -0.0412992}, {0.332342, 0.93513, 0.1228}, {0.394136, 0.904839, 0.161006}, {0.464213, 0.88476, 0.0412992}, {0.460882, 0.879345, 0.119755}, {0.454262, 0.868534, 0.198227 }, {0.33414, 0.941618, -0.041302}, {0.400968, 0.916092, -1.60812e-16}, {0.33414, 0.941618, 0.041302}, {-0.0657576, 0.859848, 0.506298}, {-0.0658169, 0.892927, 0.445365}, {-0.196015 , 0.865871, 0.460267}, {-0.196412, 0.896401, 0.397351}, {-0.131749, 0.896801, 0.422364}, {-0.0659884, 0.921919, 0.381722}, {-0.0660424, 0.946198, 0.316778}, {-0.322525, 0.855337, 0.405434 }, {-0.324864, 0.882837, 0.339209}, {-0.262661, 0.891742, 0.368518}, {-0.442867, 0.828447, 0.342848}, {-0.444464, 0.85264, 0.274694}, {-0.385906, 0.869725, 0.307659}, {-0.325929, 0.905832, 0.270627}, {-0.32553, 0.92388, 0.201189}, {-0.264151, 0.93605, 0.232455}, {-0.0665669, 0.966643, 0.247326}, {-0.0666044, 0.981483, 0.179596}, {-0.198337, 0.961188, 0.19178}, {-0.19858, 0.97237, 0.122729}, {-0.133256, 0.979426, 0.151549}, {-0.0667094, 0.991648, 0.110385}, {-0.0667413, 0.996917, 0.0412484}, {-0.198387, 0.922682, 0.330607}, {-0.199094, 0.944433 , 0.26155}, {-0.13257, 0.947822, 0.289929}, {-0.55474, 0.785715, 0.273707}, {-0.564513, 0.801504, 0.197274}, {-0.511205, 0.827147, 0.233445}, {-0.656006, 0.727958, 0.199331}, {-0.662842 , 0.738886, 0.121193}, {-0.615456, 0.771841, 0.159613}, {-0.57114, 0.812169, 0.119078}, {-0.574458, 0.817523, 0.0406752}, {-0.52411, 0.848029, 0.0784591}, {-0.744727, 0.656282, 0.121144}, {-0.749387, 0.660884, 0.0406421}, {-0.708969, 0.700622, 0.080573}, {-0.819207, 0.572056, 0.0406404}, {-0.819207, 0.572056, -0.0406404}, {-0.786433, 0.617676, -1.60812e-16}, {-0.749387 , 0.660884, -0.0406421}, {-0.744727, 0.656282, -0.121144}, {-0.708969, 0.700622, -0.080573}, {-0.574458, 0.817523, -0.0406752}, {-0.57114, 0.812169, -0.119078}, {-0.52411, 0.848029, -0.0784591 }, {-0.662842, 0.738886, -0.121193}, {-0.656006, 0.727958, -0.199331}, {-0.615456, 0.771841, -0.159613}, {-0.564513, 0.801504, -0.197274}, {-0.55474, 0.785715, -0.273707}, {-0.511205 , 0.827147, -0.233445}, {-0.667502, 0.743496, 0.0406771}, {-0.667502, 0.743496, -0.0406771}, {-0.622292, 0.782786, -1.60812e-16}, {-0.0667413, 0.996917, -0.0412484}, {-0.0667094, 0.991648 , -0.110385}, {-0.19858, 0.97237, -0.122729}, {-0.198337, 0.961188, -0.19178}, {-0.133256, 0.979426, -0.151549}, {-0.0666044, 0.981483, -0.179596}, {-0.0665669, 0.966643, -0.247326}, {-0.32553, 0.92388, -0.201189}, {-0.325929, 0.905832, -0.270627}, {-0.264151, 0.93605, -0.232455}, {-0.444464, 0.85264, -0.274694}, {-0.442867, 0.828447, -0.342848}, {-0.385906, 0.869725 , -0.307659}, {-0.324864, 0.882837, -0.339209}, {-0.322525, 0.855337, -0.405434}, {-0.262661, 0.891742, -0.368518}, {-0.0660424, 0.946198, -0.316778}, {-0.0659884, 0.921919, -0.381722}, {-0.196412, 0.896401, -0.397351}, {-0.196015, 0.865871, -0.460267}, {-0.131749, 0.896801, -0.422364}, {-0.0658169, 0.892927, -0.445365}, {-0.0657576, 0.859848, -0.506298}, {-0.199094 , 0.944433, -0.26155}, {-0.198387, 0.922682, -0.330607}, {-0.13257, 0.947822, -0.289929}, {-0.454262, 0.868534, 0.198227}, {-0.464213, 0.88476, 0.0412992}, {-0.460882, 0.879345, 0.119755 }, {-0.394136, 0.904839, 0.161006}, {-0.332342, 0.93513, 0.1228}, {-0.460882, 0.879345, -0.119755}, {-0.464213, 0.88476, -0.0412992}, {-0.454262, 0.868534, -0.198227}, {-0.394136, 0.904839, -0.161006}, {-0.332342, 0.93513, -0.1228}, {-0.265518, 0.960655, 0.0815011}, {-0.200368, 0.978852, 0.0412509}, {-0.265518, 0.960655, -0.0815011}, {-0.200368, 0.978852, -0.0412509 }, {-0.133523, 0.991046, -1.60812e-16}, {-0.400968, 0.916092, -1.60812e-16}, {-0.33414, 0.941618, -0.041302}, {-0.33414, 0.941618, 0.041302}, {0.0657576, -0.859848, 0.506298}, {0.0658169 , -0.892927, 0.445365}, {5.41885e-17, -0.884965, 0.465658}, {0.196015, -0.865871, 0.460267}, {0.196412, -0.896401, 0.397351}, {0.131749, -0.896801, 0.422364}, {0.0659884, -0.921919, 0.381722 }, {0.0660424, -0.946198, 0.316778}, {5.76038e-17, -0.940742, 0.339123}, {0.322525, -0.855337, 0.405434}, {0.324864, -0.882837, 0.339209}, {0.262661, -0.891742, 0.368518}, {0.442867 , -0.828447, 0.342848}, {0.444464, -0.85264, 0.274694}, {0.385906, -0.869725, 0.307659}, {0.325929, -0.905832, 0.270627}, {0.32553, -0.92388, 0.201189}, {0.264151, -0.93605, 0.232455}, {0.0665669, -0.966643, 0.247326}, {0.0666044, -0.981483, 0.179596}, {5.99177e-17, -0.97853, 0.206103}, {0.198337, -0.961188, 0.19178}, {0.19858, -0.97237, 0.122729}, {0.133256, -0.979426 , 0.151549}, {0.0667094, -0.991648, 0.110385}, {0.0667413, -0.996917, 0.0412484}, {6.10858e-17, -0.997607, 0.0691416}, {0.198387, -0.922682, 0.330607}, {0.199094, -0.944433, 0.26155}, {0.13257, -0.947822, 0.289929}, {0.55474, -0.785715, 0.273707}, {0.564513, -0.801504, 0.197274}, {0.511205, -0.827147, 0.233445}, {0.656006, -0.727958, 0.199331}, {0.662842, -0.738886 , 0.121193}, {0.615456, -0.771841, 0.159613}, {0.57114, -0.812169, 0.119078}, {0.574458, -0.817523, 0.0406752}, {0.52411, -0.848029, 0.0784591}, {0.744727, -0.656282, 0.121144}, { 0.749387, -0.660884, 0.0406421}, {0.708969, -0.700622, 0.080573}, {0.819207, -0.572056, 0.0406404}, {0.819207, -0.572056, -0.0406404}, {0.786433, -0.617676, -1.60812e-16}, {0.749387, -0.660884 , -0.0406421}, {0.744727, -0.656282, -0.121144}, {0.708969, -0.700622, -0.080573}, {0.574458, -0.817523, -0.0406752}, {0.57114, -0.812169, -0.119078}, {0.52411, -0.848029, -0.0784591}, {0.662842, -0.738886, -0.121193}, {0.656006, -0.727958, -0.199331}, {0.615456, -0.771841, -0.159613}, {0.564513, -0.801504, -0.197274}, {0.55474, -0.785715, -0.273707}, {0.511205, -0.827147 , -0.233445}, {0.667502, -0.743496, 0.0406771}, {0.667502, -0.743496, -0.0406771}, {0.622292, -0.782786, -1.60812e-16}, {0.0667413, -0.996917, -0.0412484}, {0.0667094, -0.991648, -0.110385 }, {6.10858e-17, -0.997607, -0.0691416}, {0.19858, -0.97237, -0.122729}, {0.198337, -0.961188, -0.19178}, {0.133256, -0.979426, -0.151549}, {0.0666044, -0.981483, -0.179596}, {0.0665669 , -0.966643, -0.247326}, {5.99177e-17, -0.97853, -0.206103}, {0.32553, -0.92388, -0.201189}, {0.325929, -0.905832, -0.270627}, {0.264151, -0.93605, -0.232455}, {0.444464, -0.85264, -0.274694 }, {0.442867, -0.828447, -0.342848}, {0.385906, -0.869725, -0.307659}, {0.324864, -0.882837, -0.339209}, {0.322525, -0.855337, -0.405434}, {0.262661, -0.891742, -0.368518}, {0.0660424 , -0.946198, -0.316778}, {0.0659884, -0.921919, -0.381722}, {5.76038e-17, -0.940742, -0.339123}, {0.196412, -0.896401, -0.397351}, {0.196015, -0.865871, -0.460267}, {0.131749, -0.896801, - 0.422364}, {0.0658169, -0.892927, -0.445365}, {0.0657576, -0.859848, -0.506298}, {5.41885e-17, -0.884965, -0.465658}, {0.199094, -0.944433, -0.26155}, {0.198387, -0.922682, -0.330607}, {0.13257, -0.947822, -0.289929}, {0.454262, -0.868534, 0.198227}, {0.464213, -0.88476, 0.0412992}, {0.460882, -0.879345, 0.119755}, {0.394136, -0.904839, 0.161006}, {0.332342, -0.93513 , 0.1228}, {0.460882, -0.879345, -0.119755}, {0.464213, -0.88476, -0.0412992}, {0.454262, -0.868534, -0.198227}, {0.394136, -0.904839, -0.161006}, {0.332342, -0.93513, -0.1228}, { 0.265518, -0.960655, 0.0815011}, {0.200368, -0.978852, 0.0412509}, {0.265518, -0.960655, -0.0815011}, {0.200368, -0.978852, -0.0412509}, {0.133523, -0.991046, -1.60812e-16}, {0.400968, - 0.916092, -1.60812e-16}, {0.33414, -0.941618, -0.041302}, {0.33414, -0.941618, 0.041302}, {-0.0658169, -0.892927, 0.445365}, {-0.0657576, -0.859848, 0.506298}, {-0.0660424, -0.946198, 0.316778 }, {-0.0659884, -0.921919, 0.381722}, {-0.131749, -0.896801, 0.422364}, {-0.196412, -0.896401, 0.397351}, {-0.196015, -0.865871, 0.460267}, {-0.0666044, -0.981483, 0.179596}, {-0.0665669 , -0.966643, 0.247326}, {-0.0667413, -0.996917, 0.0412484}, {-0.0667094, -0.991648, 0.110385}, {-0.133256, -0.979426, 0.151549}, {-0.19858, -0.97237, 0.122729}, {-0.198337, -0.961188, 0.19178 }, {-0.262661, -0.891742, 0.368518}, {-0.324864, -0.882837, 0.339209}, {-0.322525, -0.855337, 0.405434}, {-0.264151, -0.93605, 0.232455}, {-0.32553, -0.92388, 0.201189}, {-0.325929 , -0.905832, 0.270627}, {-0.385906, -0.869725, 0.307659}, {-0.444464, -0.85264, 0.274694}, {-0.442867, -0.828447, 0.342848}, {-0.13257, -0.947822, 0.289929}, {-0.199094, -0.944433, 0.26155 }, {-0.198387, -0.922682, 0.330607}, {-0.0667094, -0.991648, -0.110385}, {-0.0667413, -0.996917, -0.0412484}, {-0.0665669, -0.966643, -0.247326}, {-0.0666044, -0.981483, -0.179596}, {- 0.133256, -0.979426, -0.151549}, {-0.198337, -0.961188, -0.19178}, {-0.19858, -0.97237, -0.122729}, {-0.0659884, -0.921919, -0.381722}, {-0.0660424, -0.946198, -0.316778}, {-0.0657576, - 0.859848, -0.506298}, {-0.0658169, -0.892927, -0.445365}, {-0.131749, -0.896801, -0.422364}, {-0.196015, -0.865871, -0.460267}, {-0.196412, -0.896401, -0.397351}, {-0.264151, -0.93605, - 0.232455}, {-0.325929, -0.905832, -0.270627}, {-0.32553, -0.92388, -0.201189}, {-0.262661, -0.891742, -0.368518}, {-0.322525, -0.855337, -0.405434}, {-0.324864, -0.882837, -0.339209}, {-0.385906, -0.869725, -0.307659}, {-0.442867, -0.828447, -0.342848}, {-0.444464, -0.85264, -0.274694}, {-0.13257, -0.947822, -0.289929}, {-0.198387, -0.922682, -0.330607}, {-0.199094 , -0.944433, -0.26155}, {-0.511205, -0.827147, 0.233445}, {-0.564513, -0.801504, 0.197274}, {-0.55474, -0.785715, 0.273707}, {-0.52411, -0.848029, 0.0784591}, {-0.574458, -0.817523, 0.0406752 }, {-0.57114, -0.812169, 0.119078}, {-0.615456, -0.771841, 0.159613}, {-0.662842, -0.738886, 0.121193}, {-0.656006, -0.727958, 0.199331}, {-0.52411, -0.848029, -0.0784591}, {-0.57114 , -0.812169, -0.119078}, {-0.574458, -0.817523, -0.0406752}, {-0.511205, -0.827147, -0.233445}, {-0.55474, -0.785715, -0.273707}, {-0.564513, -0.801504, -0.197274}, {-0.615456, -0.771841 , -0.159613}, {-0.656006, -0.727958, -0.199331}, {-0.662842, -0.738886, -0.121193}, {-0.708969, -0.700622, 0.080573}, {-0.749387, -0.660884, 0.0406421}, {-0.744727, -0.656282, 0.121144}, {-0.708969, -0.700622, -0.080573}, {-0.744727, -0.656282, -0.121144}, {-0.749387, -0.660884, -0.0406421}, {-0.786433, -0.617676, -1.60812e-16}, {-0.819207, -0.572056, -0.0406404}, {- 0.819207, -0.572056, 0.0406404}, {-0.622292, -0.782786, -1.60812e-16}, {-0.667502, -0.743496, -0.0406771}, {-0.667502, -0.743496, 0.0406771}, {-0.133523, -0.991046, -1.60812e-16}, {-0.265518 , -0.960655, -0.0815011}, {-0.200368, -0.978852, -0.0412509}, {-0.200368, -0.978852, 0.0412509}, {-0.265518, -0.960655, 0.0815011}, {-0.394136, -0.904839, -0.161006}, {-0.332342, -0.93513 , -0.1228}, {-0.454262, -0.868534, -0.198227}, {-0.460882, -0.879345, -0.119755}, {-0.464213, -0.88476, -0.0412992}, {-0.332342, -0.93513, 0.1228}, {-0.394136, -0.904839, 0.161006}, {- 0.464213, -0.88476, 0.0412992}, {-0.460882, -0.879345, 0.119755}, {-0.454262, -0.868534, 0.198227}, {-0.33414, -0.941618, -0.041302}, {-0.400968, -0.916092, -1.60812e-16}, {-0.33414, -0.941618 , 0.041302}, {0.106494, 0.82711, 0.551859}, {0.237229, 0.830359, 0.504209}, {0.172532, 0.830812, 0.529135}, {0.147414, 0.79017, 0.594895}, {0.187432, 0.749786, 0.634579}, {0.366027 , 0.816233, 0.446977}, {0.303801, 0.825175, 0.476226}, {0.485712, 0.785899, 0.382683}, {0.427135, 0.803016, 0.415597}, {0.408286, 0.772575, 0.48624}, {0.448259, 0.725299, 0.522499}, { 0.38673, 0.737712, 0.553372}, {0.2289, 0.703983, 0.672319}, {0.267381, 0.65662, 0.705236}, {0.361592, 0.697037, 0.619186}, {0.399769, 0.64684, 0.649448}, {0.334692, 0.653497, 0.678913}, {0.305212, 0.605741, 0.734794}, {0.341435, 0.552454, 0.760406}, {0.280319, 0.790112, 0.545109}, {0.322141, 0.745338, 0.583691}, {0.25518, 0.749435, 0.610926}, {0.605741, 0.734794, 0.305212 }, {0.552454, 0.760406, 0.341435}, {0.703983, 0.672319, 0.2289}, {0.65662, 0.705236, 0.267381}, {0.653497, 0.678913, 0.334692}, {0.697037, 0.619186, 0.361592}, {0.64684, 0.649448, 0.399769}, {0.79017, 0.594895, 0.147414}, {0.749786, 0.634579, 0.187432}, {0.82711, 0.551859, 0.106494}, {0.830812, 0.529135, 0.172532}, {0.830359, 0.504209, 0.237229}, {0.737712, 0.553372, 0.38673}, {0.772575, 0.48624, 0.408286}, {0.725299, 0.522499, 0.448259}, {0.825175, 0.476226, 0.303801}, {0.816233, 0.446977, 0.366027}, {0.803016, 0.415597, 0.427135}, { 0.785899, 0.382683, 0.485712}, {0.749435, 0.610926, 0.25518}, {0.790112, 0.545109, 0.280319}, {0.745338, 0.583691, 0.322141}, {0.382683, 0.485712, 0.785899}, {0.415597, 0.427135, 0.803016 }, {0.522499, 0.448259, 0.725299}, {0.553372, 0.38673, 0.737712}, {0.48624, 0.408286, 0.772575}, {0.446977, 0.366027, 0.816233}, {0.476226, 0.303801, 0.825175}, {0.649448, 0.399769 , 0.64684}, {0.678913, 0.334692, 0.653497}, {0.619186, 0.361592, 0.697037}, {0.760406, 0.341435, 0.552454}, {0.734794, 0.305212, 0.605741}, {0.705236, 0.267381, 0.65662}, {0.672319 , 0.2289, 0.703983}, {0.504209, 0.237229, 0.830359}, {0.529135, 0.172532, 0.830812}, {0.634579, 0.187432, 0.749786}, {0.594895, 0.147414, 0.79017}, {0.551859, 0.106494, 0.82711}, { 0.583691, 0.322141, 0.745338}, {0.610926, 0.25518, 0.749435}, {0.545109, 0.280319, 0.790112}, {0.536784, 0.735011, 0.414273}, {0.628313, 0.619242, 0.470917}, {0.584716, 0.678977, 0.443957 }, {0.51797, 0.704471, 0.485208}, {0.496441, 0.669612, 0.552418}, {0.704471, 0.485208, 0.51797}, {0.669612, 0.552418, 0.496441}, {0.735011, 0.414273, 0.536784}, {0.678977, 0.443957 , 0.584716}, {0.619242, 0.470917, 0.628313}, {0.470917, 0.628313, 0.619242}, {0.443957, 0.584716, 0.678977}, {0.552418, 0.496441, 0.669612}, {0.485208, 0.51797, 0.704471}, {0.414273 , 0.536784, 0.735011}, {0.607478, 0.581952, 0.54065}, {0.581952, 0.54065, 0.607478}, {0.54065, 0.607478, 0.581952}, {0.106494, 0.82711, -0.551859}, {0.187432, 0.749786, -0.634579}, { 0.147414, 0.79017, -0.594895}, {0.172532, 0.830812, -0.529135}, {0.237229, 0.830359, -0.504209}, {0.267381, 0.65662, -0.705236}, {0.2289, 0.703983, -0.672319}, {0.341435, 0.552454, -0.760406 }, {0.305212, 0.605741, -0.734794}, {0.334692, 0.653497, -0.678913}, {0.399769, 0.64684, -0.649448}, {0.361592, 0.697037, -0.619186}, {0.303801, 0.825175, -0.476226}, {0.366027, 0.816233 , -0.446977}, {0.38673, 0.737712, -0.553372}, {0.448259, 0.725299, -0.522499}, {0.408286, 0.772575, -0.48624}, {0.427135, 0.803016, -0.415597}, {0.485712, 0.785899, -0.382683}, {0.25518 , 0.749435, -0.610926}, {0.322141, 0.745338, -0.583691}, {0.280319, 0.790112, -0.545109}, {0.415597, 0.427135, -0.803016}, {0.382683, 0.485712, -0.785899}, {0.476226, 0.303801, -0.825175 }, {0.446977, 0.366027, -0.816233}, {0.48624, 0.408286, -0.772575}, {0.553372, 0.38673, -0.737712}, {0.522499, 0.448259, -0.725299}, {0.529135, 0.172532, -0.830812}, {0.504209, 0.237229 , -0.830359}, {0.551859, 0.106494, -0.82711}, {0.594895, 0.147414, -0.79017}, {0.634579, 0.187432, -0.749786}, {0.619186, 0.361592, -0.697037}, {0.678913, 0.334692, -0.653497}, {0.649448 , 0.399769, -0.64684}, {0.672319, 0.2289, -0.703983}, {0.705236, 0.267381, -0.65662}, {0.734794, 0.305212, -0.605741}, {0.760406, 0.341435, -0.552454}, {0.545109, 0.280319, -0.790112}, {0.610926, 0.25518, -0.749435}, {0.583691, 0.322141, -0.745338}, {0.552454, 0.760406, -0.341435}, {0.605741, 0.734794, -0.305212}, {0.64684, 0.649448, -0.399769}, {0.697037, 0.619186 , -0.361592}, {0.653497, 0.678913, -0.334692}, {0.65662, 0.705236, -0.267381}, {0.703983, 0.672319, -0.2289}, {0.725299, 0.522499, -0.448259}, {0.772575, 0.48624, -0.408286}, {0.737712 , 0.553372, -0.38673}, {0.785899, 0.382683, -0.485712}, {0.803016, 0.415597, -0.427135}, {0.816233, 0.446977, -0.366027}, {0.825175, 0.476226, -0.303801}, {0.749786, 0.634579, -0.187432}, {0.79017, 0.594895, -0.147414}, {0.830359, 0.504209, -0.237229}, {0.830812, 0.529135, -0.172532}, {0.82711, 0.551859, -0.106494}, {0.745338, 0.583691, -0.322141}, {0.790112, 0.545109 , -0.280319}, {0.749435, 0.610926, -0.25518}, {0.414273, 0.536784, -0.735011}, {0.552418, 0.496441, -0.669612}, {0.485208, 0.51797, -0.704471}, {0.443957, 0.584716, -0.678977}, {0.470917 , 0.628313, -0.619242}, {0.678977, 0.443957, -0.584716}, {0.619242, 0.470917, -0.628313}, {0.735011, 0.414273, -0.536784}, {0.704471, 0.485208, -0.51797}, {0.669612, 0.552418, -0.496441}, {0.496441, 0.669612, -0.552418}, {0.51797, 0.704471, -0.485208}, {0.628313, 0.619242, -0.470917}, {0.584716, 0.678977, -0.443957}, {0.536784, 0.735011, -0.414273}, {0.581952, 0.54065 , -0.607478}, {0.607478, 0.581952, -0.54065}, {0.54065, 0.607478, -0.581952}, {0.551859, -0.106494, 0.82711}, {0.634579, -0.187432, 0.749786}, {0.594895, -0.147414, 0.79017}, {0.529135 , -0.172532, 0.830812}, {0.504209, -0.237229, 0.830359}, {0.705236, -0.267381, 0.65662}, {0.672319, -0.2289, 0.703983}, {0.760406, -0.341435, 0.552454}, {0.734794, -0.305212, 0.605741}, {0.678913, -0.334692, 0.653497}, {0.649448, -0.399769, 0.64684}, {0.619186, -0.361592, 0.697037}, {0.476226, -0.303801, 0.825175}, {0.446977, -0.366027, 0.816233}, {0.553372, -0.38673 , 0.737712}, {0.522499, -0.448259, 0.725299}, {0.48624, -0.408286, 0.772575}, {0.415597, -0.427135, 0.803016}, {0.382683, -0.485712, 0.785899}, {0.610926, -0.25518, 0.749435}, {0.583691 , -0.322141, 0.745338}, {0.545109, -0.280319, 0.790112}, {0.803016, -0.415597, 0.427135}, {0.785899, -0.382683, 0.485712}, {0.825175, -0.476226, 0.303801}, {0.816233, -0.446977, 0.366027 }, {0.772575, -0.48624, 0.408286}, {0.737712, -0.553372, 0.38673}, {0.725299, -0.522499, 0.448259}, {0.830812, -0.529135, 0.172532}, {0.830359, -0.504209, 0.237229}, {0.82711, -0.551859 , 0.106494}, {0.79017, -0.594895, 0.147414}, {0.749786, -0.634579, 0.187432}, {0.697037, -0.619186, 0.361592}, {0.653497, -0.678913, 0.334692}, {0.64684, -0.649448, 0.399769}, {0.703983 , -0.672319, 0.2289}, {0.65662, -0.705236, 0.267381}, {0.605741, -0.734794, 0.305212}, {0.552454, -0.760406, 0.341435}, {0.790112, -0.545109, 0.280319}, {0.749435, -0.610926, 0.25518}, {0.745338, -0.583691, 0.322141}, {0.341435, -0.552454, 0.760406}, {0.305212, -0.605741, 0.734794}, {0.399769, -0.64684, 0.649448}, {0.361592, -0.697037, 0.619186}, {0.334692, -0.653497 , 0.678913}, {0.267381, -0.65662, 0.705236}, {0.2289, -0.703983, 0.672319}, {0.448259, -0.725299, 0.522499}, {0.408286, -0.772575, 0.48624}, {0.38673, -0.737712, 0.553372}, {0.485712 , -0.785899, 0.382683}, {0.427135, -0.803016, 0.415597}, {0.366027, -0.816233, 0.446977}, {0.303801, -0.825175, 0.476226}, {0.187432, -0.749786, 0.634579}, {0.147414, -0.79017, 0.594895}, {0.237229, -0.830359, 0.504209}, {0.172532, -0.830812, 0.529135}, {0.106494, -0.82711, 0.551859}, {0.322141, -0.745338, 0.583691}, {0.280319, -0.790112, 0.545109}, {0.25518, -0.749435 , 0.610926}, {0.735011, -0.414273, 0.536784}, {0.669612, -0.552418, 0.496441}, {0.704471, -0.485208, 0.51797}, {0.678977, -0.443957, 0.584716}, {0.619242, -0.470917, 0.628313}, {0.584716 , -0.678977, 0.443957}, {0.628313, -0.619242, 0.470917}, {0.536784, -0.735011, 0.414273}, {0.51797, -0.704471, 0.485208}, {0.496441, -0.669612, 0.552418}, {0.552418, -0.496441, 0.669612}, {0.485208, -0.51797, 0.704471}, {0.470917, -0.628313, 0.619242}, {0.443957, -0.584716, 0.678977}, {0.414273, -0.536784, 0.735011}, {0.607478, -0.581952, 0.54065}, {0.54065, -0.607478 , 0.581952}, {0.581952, -0.54065, 0.607478}, {0.551859, -0.106494, -0.82711}, {0.504209, -0.237229, -0.830359}, {0.529135, -0.172532, -0.830812}, {0.594895, -0.147414, -0.79017}, { 0.634579, -0.187432, -0.749786}, {0.446977, -0.366027, -0.816233}, {0.476226, -0.303801, -0.825175}, {0.382683, -0.485712, -0.785899}, {0.415597, -0.427135, -0.803016}, {0.48624, -0.408286 , -0.772575}, {0.522499, -0.448259, -0.725299}, {0.553372, -0.38673, -0.737712}, {0.672319, -0.2289, -0.703983}, {0.705236, -0.267381, -0.65662}, {0.619186, -0.361592, -0.697037}, { 0.649448, -0.399769, -0.64684}, {0.678913, -0.334692, -0.653497}, {0.734794, -0.305212, -0.605741}, {0.760406, -0.341435, -0.552454}, {0.545109, -0.280319, -0.790112}, {0.583691, -0.322141 , -0.745338}, {0.610926, -0.25518, -0.749435}, {0.305212, -0.605741, -0.734794}, {0.341435, -0.552454, -0.760406}, {0.2289, -0.703983, -0.672319}, {0.267381, -0.65662, -0.705236}, { 0.334692, -0.653497, -0.678913}, {0.361592, -0.697037, -0.619186}, {0.399769, -0.64684, -0.649448}, {0.147414, -0.79017, -0.594895}, {0.187432, -0.749786, -0.634579}, {0.106494, -0.82711 , -0.551859}, {0.172532, -0.830812, -0.529135}, {0.237229, -0.830359, -0.504209}, {0.38673, -0.737712, -0.553372}, {0.408286, -0.772575, -0.48624}, {0.448259, -0.725299, -0.522499}, { 0.303801, -0.825175, -0.476226}, {0.366027, -0.816233, -0.446977}, {0.427135, -0.803016, -0.415597}, {0.485712, -0.785899, -0.382683}, {0.25518, -0.749435, -0.610926}, {0.280319, -0.790112 , -0.545109}, {0.322141, -0.745338, -0.583691}, {0.785899, -0.382683, -0.485712}, {0.803016, -0.415597, -0.427135}, {0.725299, -0.522499, -0.448259}, {0.737712, -0.553372, -0.38673}, {0.772575, -0.48624, -0.408286}, {0.816233, -0.446977, -0.366027}, {0.825175, -0.476226, -0.303801}, {0.64684, -0.649448, -0.399769}, {0.653497, -0.678913, -0.334692}, {0.697037, -0.619186 , -0.361592}, {0.552454, -0.760406, -0.341435}, {0.605741, -0.734794, -0.305212}, {0.65662, -0.705236, -0.267381}, {0.703983, -0.672319, -0.2289}, {0.830359, -0.504209, -0.237229}, { 0.830812, -0.529135, -0.172532}, {0.749786, -0.634579, -0.187432}, {0.79017, -0.594895, -0.147414}, {0.82711, -0.551859, -0.106494}, {0.745338, -0.583691, -0.322141}, {0.749435, -0.610926 , -0.25518}, {0.790112, -0.545109, -0.280319}, {0.414273, -0.536784, -0.735011}, {0.470917, -0.628313, -0.619242}, {0.443957, -0.584716, -0.678977}, {0.485208, -0.51797, -0.704471}, { 0.552418, -0.496441, -0.669612}, {0.51797, -0.704471, -0.485208}, {0.496441, -0.669612, -0.552418}, {0.536784, -0.735011, -0.414273}, {0.584716, -0.678977, -0.443957}, {0.628313, -0.619242 , -0.470917}, {0.619242, -0.470917, -0.628313}, {0.678977, -0.443957, -0.584716}, {0.669612, -0.552418, -0.496441}, {0.704471, -0.485208, -0.51797}, {0.735011, -0.414273, -0.536784}, {0.54065, -0.607478, -0.581952}, {0.607478, -0.581952, -0.54065}, {0.581952, -0.54065, -0.607478}, {-0.551859, 0.106494, 0.82711}, {-0.634579, 0.187432, 0.749786}, {-0.594895, 0.147414 , 0.79017}, {-0.529135, 0.172532, 0.830812}, {-0.504209, 0.237229, 0.830359}, {-0.705236, 0.267381, 0.65662}, {-0.672319, 0.2289, 0.703983}, {-0.760406, 0.341435, 0.552454}, {-0.734794 , 0.305212, 0.605741}, {-0.678913, 0.334692, 0.653497}, {-0.649448, 0.399769, 0.64684}, {-0.619186, 0.361592, 0.697037}, {-0.476226, 0.303801, 0.825175}, {-0.446977, 0.366027, 0.816233}, {-0.553372, 0.38673, 0.737712}, {-0.522499, 0.448259, 0.725299}, {-0.48624, 0.408286, 0.772575}, {-0.415597, 0.427135, 0.803016}, {-0.382683, 0.485712, 0.785899}, {-0.610926, 0.25518 , 0.749435}, {-0.583691, 0.322141, 0.745338}, {-0.545109, 0.280319, 0.790112}, {-0.803016, 0.415597, 0.427135}, {-0.785899, 0.382683, 0.485712}, {-0.825175, 0.476226, 0.303801}, {- 0.816233, 0.446977, 0.366027}, {-0.772575, 0.48624, 0.408286}, {-0.737712, 0.553372, 0.38673}, {-0.725299, 0.522499, 0.448259}, {-0.830812, 0.529135, 0.172532}, {-0.830359, 0.504209, 0.237229 }, {-0.82711, 0.551859, 0.106494}, {-0.79017, 0.594895, 0.147414}, {-0.749786, 0.634579, 0.187432}, {-0.697037, 0.619186, 0.361592}, {-0.653497, 0.678913, 0.334692}, {-0.64684, 0.649448 , 0.399769}, {-0.703983, 0.672319, 0.2289}, {-0.65662, 0.705236, 0.267381}, {-0.605741, 0.734794, 0.305212}, {-0.552454, 0.760406, 0.341435}, {-0.790112, 0.545109, 0.280319}, {-0.749435 , 0.610926, 0.25518}, {-0.745338, 0.583691, 0.322141}, {-0.341435, 0.552454, 0.760406}, {-0.305212, 0.605741, 0.734794}, {-0.399769, 0.64684, 0.649448}, {-0.361592, 0.697037, 0.619186}, {-0.334692, 0.653497, 0.678913}, {-0.267381, 0.65662, 0.705236}, {-0.2289, 0.703983, 0.672319}, {-0.448259, 0.725299, 0.522499}, {-0.408286, 0.772575, 0.48624}, {-0.38673, 0.737712, 0.553372}, {-0.485712, 0.785899, 0.382683}, {-0.427135, 0.803016, 0.415597}, {-0.366027, 0.816233, 0.446977}, {-0.303801, 0.825175, 0.476226}, {-0.187432, 0.749786, 0.634579}, {-0.147414 , 0.79017, 0.594895}, {-0.237229, 0.830359, 0.504209}, {-0.172532, 0.830812, 0.529135}, {-0.106494, 0.82711, 0.551859}, {-0.322141, 0.745338, 0.583691}, {-0.280319, 0.790112, 0.545109}, {-0.25518, 0.749435, 0.610926}, {-0.735011, 0.414273, 0.536784}, {-0.669612, 0.552418, 0.496441}, {-0.704471, 0.485208, 0.51797}, {-0.678977, 0.443957, 0.584716}, {-0.619242, 0.470917 , 0.628313}, {-0.584716, 0.678977, 0.443957}, {-0.628313, 0.619242, 0.470917}, {-0.536784, 0.735011, 0.414273}, {-0.51797, 0.704471, 0.485208}, {-0.496441, 0.669612, 0.552418}, {- 0.552418, 0.496441, 0.669612}, {-0.485208, 0.51797, 0.704471}, {-0.470917, 0.628313, 0.619242}, {-0.443957, 0.584716, 0.678977}, {-0.414273, 0.536784, 0.735011}, {-0.607478, 0.581952, 0.54065 }, {-0.54065, 0.607478, 0.581952}, {-0.581952, 0.54065, 0.607478}, {-0.551859, 0.106494, -0.82711}, {-0.504209, 0.237229, -0.830359}, {-0.529135, 0.172532, -0.830812}, {-0.594895, 0.147414, -0.79017}, {-0.634579, 0.187432, -0.749786}, {-0.446977, 0.366027, -0.816233}, {-0.476226, 0.303801, -0.825175}, {-0.382683, 0.485712, -0.785899}, {-0.415597, 0.427135, -0.803016 }, {-0.48624, 0.408286, -0.772575}, {-0.522499, 0.448259, -0.725299}, {-0.553372, 0.38673, -0.737712}, {-0.672319, 0.2289, -0.703983}, {-0.705236, 0.267381, -0.65662}, {-0.619186, 0.361592, -0.697037}, {-0.649448, 0.399769, -0.64684}, {-0.678913, 0.334692, -0.653497}, {-0.734794, 0.305212, -0.605741}, {-0.760406, 0.341435, -0.552454}, {-0.545109, 0.280319, -0.790112 }, {-0.583691, 0.322141, -0.745338}, {-0.610926, 0.25518, -0.749435}, {-0.305212, 0.605741, -0.734794}, {-0.341435, 0.552454, -0.760406}, {-0.2289, 0.703983, -0.672319}, {-0.267381 , 0.65662, -0.705236}, {-0.334692, 0.653497, -0.678913}, {-0.361592, 0.697037, -0.619186}, {-0.399769, 0.64684, -0.649448}, {-0.147414, 0.79017, -0.594895}, {-0.187432, 0.749786, -0.634579 }, {-0.106494, 0.82711, -0.551859}, {-0.172532, 0.830812, -0.529135}, {-0.237229, 0.830359, -0.504209}, {-0.38673, 0.737712, -0.553372}, {-0.408286, 0.772575, -0.48624}, {-0.448259 , 0.725299, -0.522499}, {-0.303801, 0.825175, -0.476226}, {-0.366027, 0.816233, -0.446977}, {-0.427135, 0.803016, -0.415597}, {-0.485712, 0.785899, -0.382683}, {-0.25518, 0.749435, -0.610926 }, {-0.280319, 0.790112, -0.545109}, {-0.322141, 0.745338, -0.583691}, {-0.785899, 0.382683, -0.485712}, {-0.803016, 0.415597, -0.427135}, {-0.725299, 0.522499, -0.448259}, {-0.737712 , 0.553372, -0.38673}, {-0.772575, 0.48624, -0.408286}, {-0.816233, 0.446977, -0.366027}, {-0.825175, 0.476226, -0.303801}, {-0.64684, 0.649448, -0.399769}, {-0.653497, 0.678913, -0.334692 }, {-0.697037, 0.619186, -0.361592}, {-0.552454, 0.760406, -0.341435}, {-0.605741, 0.734794, -0.305212}, {-0.65662, 0.705236, -0.267381}, {-0.703983, 0.672319, -0.2289}, {-0.830359 , 0.504209, -0.237229}, {-0.830812, 0.529135, -0.172532}, {-0.749786, 0.634579, -0.187432}, {-0.79017, 0.594895, -0.147414}, {-0.82711, 0.551859, -0.106494}, {-0.745338, 0.583691, -0.322141 }, {-0.749435, 0.610926, -0.25518}, {-0.790112, 0.545109, -0.280319}, {-0.414273, 0.536784, -0.735011}, {-0.470917, 0.628313, -0.619242}, {-0.443957, 0.584716, -0.678977}, {-0.485208 , 0.51797, -0.704471}, {-0.552418, 0.496441, -0.669612}, {-0.51797, 0.704471, -0.485208}, {-0.496441, 0.669612, -0.552418}, {-0.536784, 0.735011, -0.414273}, {-0.584716, 0.678977, -0.443957 }, {-0.628313, 0.619242, -0.470917}, {-0.619242, 0.470917, -0.628313}, {-0.678977, 0.443957, -0.584716}, {-0.669612, 0.552418, -0.496441}, {-0.704471, 0.485208, -0.51797}, {-0.735011 , 0.414273, -0.536784}, {-0.54065, 0.607478, -0.581952}, {-0.607478, 0.581952, -0.54065}, {-0.581952, 0.54065, -0.607478}, {-0.551859, -0.106494, 0.82711}, {-0.504209, -0.237229, 0.830359 }, {-0.529135, -0.172532, 0.830812}, {-0.594895, -0.147414, 0.79017}, {-0.634579, -0.187432, 0.749786}, {-0.446977, -0.366027, 0.816233}, {-0.476226, -0.303801, 0.825175}, {-0.382683 , -0.485712, 0.785899}, {-0.415597, -0.427135, 0.803016}, {-0.48624, -0.408286, 0.772575}, {-0.522499, -0.448259, 0.725299}, {-0.553372, -0.38673, 0.737712}, {-0.672319, -0.2289, 0.703983 }, {-0.705236, -0.267381, 0.65662}, {-0.619186, -0.361592, 0.697037}, {-0.649448, -0.399769, 0.64684}, {-0.678913, -0.334692, 0.653497}, {-0.734794, -0.305212, 0.605741}, {-0.760406 , -0.341435, 0.552454}, {-0.545109, -0.280319, 0.790112}, {-0.583691, -0.322141, 0.745338}, {-0.610926, -0.25518, 0.749435}, {-0.305212, -0.605741, 0.734794}, {-0.341435, -0.552454, 0.760406 }, {-0.2289, -0.703983, 0.672319}, {-0.267381, -0.65662, 0.705236}, {-0.334692, -0.653497, 0.678913}, {-0.361592, -0.697037, 0.619186}, {-0.399769, -0.64684, 0.649448}, {-0.147414 , -0.79017, 0.594895}, {-0.187432, -0.749786, 0.634579}, {-0.106494, -0.82711, 0.551859}, {-0.172532, -0.830812, 0.529135}, {-0.237229, -0.830359, 0.504209}, {-0.38673, -0.737712, 0.553372 }, {-0.408286, -0.772575, 0.48624}, {-0.448259, -0.725299, 0.522499}, {-0.303801, -0.825175, 0.476226}, {-0.366027, -0.816233, 0.446977}, {-0.427135, -0.803016, 0.415597}, {-0.485712 , -0.785899, 0.382683}, {-0.25518, -0.749435, 0.610926}, {-0.280319, -0.790112, 0.545109}, {-0.322141, -0.745338, 0.583691}, {-0.785899, -0.382683, 0.485712}, {-0.803016, -0.415597, 0.427135 }, {-0.725299, -0.522499, 0.448259}, {-0.737712, -0.553372, 0.38673}, {-0.772575, -0.48624, 0.408286}, {-0.816233, -0.446977, 0.366027}, {-0.825175, -0.476226, 0.303801}, {-0.64684 , -0.649448, 0.399769}, {-0.653497, -0.678913, 0.334692}, {-0.697037, -0.619186, 0.361592}, {-0.552454, -0.760406, 0.341435}, {-0.605741, -0.734794, 0.305212}, {-0.65662, -0.705236, 0.267381 }, {-0.703983, -0.672319, 0.2289}, {-0.830359, -0.504209, 0.237229}, {-0.830812, -0.529135, 0.172532}, {-0.749786, -0.634579, 0.187432}, {-0.79017, -0.594895, 0.147414}, {-0.82711 , -0.551859, 0.106494}, {-0.745338, -0.583691, 0.322141}, {-0.749435, -0.610926, 0.25518}, {-0.790112, -0.545109, 0.280319}, {-0.414273, -0.536784, 0.735011}, {-0.470917, -0.628313, 0.619242 }, {-0.443957, -0.584716, 0.678977}, {-0.485208, -0.51797, 0.704471}, {-0.552418, -0.496441, 0.669612}, {-0.51797, -0.704471, 0.485208}, {-0.496441, -0.669612, 0.552418}, {-0.536784 , -0.735011, 0.414273}, {-0.584716, -0.678977, 0.443957}, {-0.628313, -0.619242, 0.470917}, {-0.619242, -0.470917, 0.628313}, {-0.678977, -0.443957, 0.584716}, {-0.669612, -0.552418, 0.496441 }, {-0.704471, -0.485208, 0.51797}, {-0.735011, -0.414273, 0.536784}, {-0.54065, -0.607478, 0.581952}, {-0.607478, -0.581952, 0.54065}, {-0.581952, -0.54065, 0.607478}, {-0.551859 , -0.106494, -0.82711}, {-0.634579, -0.187432, -0.749786}, {-0.594895, -0.147414, -0.79017}, {-0.529135, -0.172532, -0.830812}, {-0.504209, -0.237229, -0.830359}, {-0.705236, -0.267381, - 0.65662}, {-0.672319, -0.2289, -0.703983}, {-0.760406, -0.341435, -0.552454}, {-0.734794, -0.305212, -0.605741}, {-0.678913, -0.334692, -0.653497}, {-0.649448, -0.399769, -0.64684}, {- 0.619186, -0.361592, -0.697037}, {-0.476226, -0.303801, -0.825175}, {-0.446977, -0.366027, -0.816233}, {-0.553372, -0.38673, -0.737712}, {-0.522499, -0.448259, -0.725299}, {-0.48624, -0.408286 , -0.772575}, {-0.415597, -0.427135, -0.803016}, {-0.382683, -0.485712, -0.785899}, {-0.610926, -0.25518, -0.749435}, {-0.583691, -0.322141, -0.745338}, {-0.545109, -0.280319, -0.790112}, {-0.803016, -0.415597, -0.427135}, {-0.785899, -0.382683, -0.485712}, {-0.825175, -0.476226, -0.303801}, {-0.816233, -0.446977, -0.366027}, {-0.772575, -0.48624, -0.408286}, {-0.737712 , -0.553372, -0.38673}, {-0.725299, -0.522499, -0.448259}, {-0.830812, -0.529135, -0.172532}, {-0.830359, -0.504209, -0.237229}, {-0.82711, -0.551859, -0.106494}, {-0.79017, -0.594895, - 0.147414}, {-0.749786, -0.634579, -0.187432}, {-0.697037, -0.619186, -0.361592}, {-0.653497, -0.678913, -0.334692}, {-0.64684, -0.649448, -0.399769}, {-0.703983, -0.672319, -0.2289}, {-0.65662, -0.705236, -0.267381}, {-0.605741, -0.734794, -0.305212}, {-0.552454, -0.760406, -0.341435}, {-0.790112, -0.545109, -0.280319}, {-0.749435, -0.610926, -0.25518}, {-0.745338 , -0.583691, -0.322141}, {-0.341435, -0.552454, -0.760406}, {-0.305212, -0.605741, -0.734794}, {-0.399769, -0.64684, -0.649448}, {-0.361592, -0.697037, -0.619186}, {-0.334692, -0.653497, - 0.678913}, {-0.267381, -0.65662, -0.705236}, {-0.2289, -0.703983, -0.672319}, {-0.448259, -0.725299, -0.522499}, {-0.408286, -0.772575, -0.48624}, {-0.38673, -0.737712, -0.553372}, {- 0.485712, -0.785899, -0.382683}, {-0.427135, -0.803016, -0.415597}, {-0.366027, -0.816233, -0.446977}, {-0.303801, -0.825175, -0.476226}, {-0.187432, -0.749786, -0.634579}, {-0.147414, - 0.79017, -0.594895}, {-0.237229, -0.830359, -0.504209}, {-0.172532, -0.830812, -0.529135}, {-0.106494, -0.82711, -0.551859}, {-0.322141, -0.745338, -0.583691}, {-0.280319, -0.790112, -0.545109 }, {-0.25518, -0.749435, -0.610926}, {-0.735011, -0.414273, -0.536784}, {-0.669612, -0.552418, -0.496441}, {-0.704471, -0.485208, -0.51797}, {-0.678977, -0.443957, -0.584716}, {-0.619242 , -0.470917, -0.628313}, {-0.584716, -0.678977, -0.443957}, {-0.628313, -0.619242, -0.470917}, {-0.536784, -0.735011, -0.414273}, {-0.51797, -0.704471, -0.485208}, {-0.496441, -0.669612, - 0.552418}, {-0.552418, -0.496441, -0.669612}, {-0.485208, -0.51797, -0.704471}, {-0.470917, -0.628313, -0.619242}, {-0.443957, -0.584716, -0.678977}, {-0.414273, -0.536784, -0.735011}, {-0.607478, -0.581952, -0.54065}, {-0.54065, -0.607478, -0.581952}, {-0.581952, -0.54065, -0.607478} }; TractOrientationContainerType::Pointer sdcontainerptr = TractOrientationContainerType::New(); for(unsigned int i = 0; iInsertElement(i, dir); } this->SetSampleDirections( sdcontainerptr ); } } diff --git a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp index 2123b64c1a..b74a54a9bf 100644 --- a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp +++ b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp @@ -1,638 +1,653 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkGibbsTrackingFilter.h" #include #include #include "itkPointShell.h" #include "GibbsTracking/BuildFibres.cpp" #pragma GCC visibility push(default) #include #pragma GCC visibility pop #include #include #include #include #include #include #include #include #include #include struct LessDereference { template bool operator()(const T * lhs, const T * rhs) const { return *lhs < *rhs; } }; namespace itk{ template< class TInputOdfImage, class TInputROIImage > GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::GibbsTrackingFilter(): m_TempStart(0.1), m_TempEnd(0.001), m_NumIt(500000), m_ParticleWeight(0), m_ParticleWidth(0), m_ParticleLength(0), m_ChempotConnection(10), m_ChempotParticle(0), m_InexBalance(0), m_Chempot2(0.2), m_FiberLength(10), m_AbortTracking(false), m_NumConnections(0), m_NumParticles(0), m_NumAcceptedFibers(0), m_CurrentStep(0), m_SubtractMean(true), m_BuildFibers(false), m_Sampler(NULL), m_Steps(10), m_Memory(0), m_ProposalAcceptance(0), m_GfaImage(NULL), m_CurvatureHardThreshold(0.7), m_Meanval_sq(0.0) { //this->m_MeasurementFrame.set_identity(); this->SetNumberOfRequiredInputs(2); //Filter needs a DWI image + a Mask Image } template< class TInputOdfImage, class TInputROIImage > GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::~GibbsTrackingFilter(){ delete BESSEL_APPROXCOEFF; if (m_Sampler!=NULL) delete m_Sampler; } template< class TInputOdfImage, class TInputROIImage > void GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::ComputeFiberCorrelationOriginal(){ float bD = 15; vnl_matrix_fixed bDir = *itk::PointShell >::DistributePointShell(); const int N = QBALL_ODFSIZE; vnl_matrix_fixed C = bDir.transpose()*bDir; vnl_matrix_fixed Q = C; for(int i=0; i P = Q*Q; std::vector pointer; pointer.reserve(N*N); double * start = C.data_block(); double * end = start + N*N; for (double * iter = start; iter != end; ++iter) { pointer.push_back(iter); } std::sort(pointer.begin(), pointer.end(), LessDereference()); vnl_vector_fixed alpha; vnl_vector_fixed beta; for (int i=0; i alpha_0; vnl_vector_fixed alpha_2; vnl_vector_fixed alpha_4; vnl_vector_fixed alpha_6; for(int i=0; i T; T.set_column(0,alpha_0); T.set_column(1,alpha_2); T.set_column(2,alpha_4); T.set_column(3,alpha_6); vnl_vector_fixed coeff = vnl_matrix_inverse(T).pinverse()*beta; BESSEL_APPROXCOEFF = new float[4]; BESSEL_APPROXCOEFF[0] = coeff(0); BESSEL_APPROXCOEFF[1] = coeff(1); BESSEL_APPROXCOEFF[2] = coeff(2); BESSEL_APPROXCOEFF[3] = coeff(3); // // OLD // BESSEL_APPROXCOEFF[0] = 0,1982; // BESSEL_APPROXCOEFF[1] = 0.3415; // BESSEL_APPROXCOEFF[2] = -0.9515; // BESSEL_APPROXCOEFF[3] = 1.3423; } template< class TInputOdfImage, class TInputROIImage > void GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::ComputeFiberCorrelation(){ // float bD = 15; // vnl_matrix_fixed bDir = // *itk::PointShell >::DistributePointShell(); // const int N = QBALL_ODFSIZE; // vnl_matrix_fixed temp = bDir.transpose(); // vnl_matrix_fixed C = temp*bDir; // vnl_matrix_fixed Q = C; // vnl_vector_fixed mean; // for(int i=0; i repMean; // for (int i=0; i P = Q*Q; // std::vector pointer; // pointer.reserve(N*N); // double * start = C.data_block(); // double * end = start + N*N; // for (double * iter = start; iter != end; ++iter) // { // pointer.push_back(iter); // } // std::sort(pointer.begin(), pointer.end(), LessDereference()); // vnl_vector_fixed alpha; // vnl_vector_fixed beta; // for (int i=0; im_Meanval_sq = (sum*sum)/N; // vnl_vector_fixed alpha_0; // vnl_vector_fixed alpha_2; // vnl_vector_fixed alpha_4; // vnl_vector_fixed alpha_6; // for(int i=0; i T; // T.set_column(0,alpha_0); // T.set_column(1,alpha_2); // T.set_column(2,alpha_4); // T.set_column(3,alpha_6); // vnl_vector_fixed coeff = vnl_matrix_inverse(T).pinverse()*beta; // MITK_INFO << "itkGibbsTrackingFilter: Bessel oefficients: " << coeff; BESSEL_APPROXCOEFF = new float[4]; // BESSEL_APPROXCOEFF[0] = coeff(0); // BESSEL_APPROXCOEFF[1] = coeff(1); // BESSEL_APPROXCOEFF[2] = coeff(2); // BESSEL_APPROXCOEFF[3] = coeff(3); BESSEL_APPROXCOEFF[0] = -0.1714; BESSEL_APPROXCOEFF[1] = 0.5332; BESSEL_APPROXCOEFF[2] = -1.4889; BESSEL_APPROXCOEFF[3] = 2.0389; } // build fibers from tracking result template< class TInputOdfImage, class TInputROIImage > void GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::BuildFibers(float* points, int numPoints) { double spacing[3]; spacing[0] = m_ItkQBallImage->GetSpacing().GetElement(0); spacing[1] = m_ItkQBallImage->GetSpacing().GetElement(1); spacing[2] = m_ItkQBallImage->GetSpacing().GetElement(2); m_FiberPolyData = FiberPolyDataType::New(); // initialize array of particles FiberBuilder fiberBuilder(points, numPoints, spacing, m_ItkQBallImage); // label the particles according to fiber affiliation and return polydata m_FiberPolyData = fiberBuilder.iterate(m_FiberLength); m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines(); MITK_INFO << "itkGibbsTrackingFilter: " << m_NumAcceptedFibers << " accepted"; } // fill output fiber bundle datastructure template< class TInputOdfImage, class TInputROIImage > typename GibbsTrackingFilter< TInputOdfImage, TInputROIImage >::FiberPolyDataType GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::GetFiberBundle() { if (!m_AbortTracking) { m_BuildFibers = true; while (m_BuildFibers){} } return m_FiberPolyData; } // get memory allocated for particle grid template< class TInputOdfImage, class TInputROIImage > float GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::GetMemoryUsage() { if (m_Sampler!=NULL) return m_Sampler->m_ParticleGrid.GetMemoryUsage(); return 0; } template< class TInputOdfImage, class TInputROIImage > bool GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::EstimateParticleWeight() { MITK_INFO << "itkGibbsTrackingFilter: estimating particle weight"; typedef itk::DiffusionQballGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(m_ItkQBallImage); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); m_GfaImage = gfaFilter->GetOutput(); float samplingStart = 1.0; float samplingStop = 0.66; // copy GFA image (original should not be changed) typedef itk::ImageDuplicator< GfaImageType > DuplicateFilterType; DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); duplicator->SetInputImage( m_GfaImage ); duplicator->Update(); m_GfaImage = duplicator->GetOutput(); //// GFA iterator //// typedef ImageRegionIterator< GfaImageType > GfaIteratorType; GfaIteratorType gfaIt(m_GfaImage, m_GfaImage->GetLargestPossibleRegion() ); //// Mask iterator //// typedef ImageRegionConstIterator< MaskImageType > MaskIteratorType; MaskIteratorType maskIt(m_MaskImage, m_MaskImage->GetLargestPossibleRegion() ); // set unmasked region of gfa image to 0 gfaIt.GoToBegin(); maskIt.GoToBegin(); while( !gfaIt.IsAtEnd() ) { if(maskIt.Get()<=0) gfaIt.Set(0); ++gfaIt; ++maskIt; } // rescale gfa image to [0,1] typedef itk::RescaleIntensityImageFilter< GfaImageType, GfaImageType > RescaleFilterType; RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetInput( m_GfaImage ); rescaleFilter->SetOutputMaximum( samplingStart ); rescaleFilter->SetOutputMinimum( 0 ); rescaleFilter->Update(); m_GfaImage = rescaleFilter->GetOutput(); gfaIt = GfaIteratorType(m_GfaImage, m_GfaImage->GetLargestPossibleRegion() ); //// Input iterator //// typedef ImageRegionConstIterator< InputQBallImageType > InputIteratorType; InputIteratorType git(m_ItkQBallImage, m_ItkQBallImage->GetLargestPossibleRegion() ); float upper = 0; int count = 0; for(float thr=samplingStart; thr>samplingStop; thr-=0.01) { git.GoToBegin(); gfaIt.GoToBegin(); while( !gfaIt.IsAtEnd() ) { if(gfaIt.Get()>thr) { itk::OrientationDistributionFunction odf(git.Get().GetDataPointer()); upper += odf.GetMaxValue()-odf.GetMeanValue(); ++count; } ++gfaIt; ++git; } } if (count>0) upper /= count; else return false; m_ParticleWeight = upper/6; return true; } // perform global tracking template< class TInputOdfImage, class TInputROIImage > void GibbsTrackingFilter< TInputOdfImage, TInputROIImage > ::GenerateData(){ // input qball image m_ItkQBallImage = dynamic_cast(this->GetInput(0)); m_NumAcceptedFibers = 0; // approximationscoeffizienten der // teilchenkorrelationen im orientierungsraum // 4er vektor //ComputeFiberCorrelationOriginal(); ComputeFiberCorrelation(); // image sizes and spacing int qBallImageSize[4] = {QBALL_ODFSIZE, m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(0), m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(1), m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(2)}; double qBallImageSpacing[3] = {m_ItkQBallImage->GetSpacing().GetElement(0),m_ItkQBallImage->GetSpacing().GetElement(1),m_ItkQBallImage->GetSpacing().GetElement(2)}; // make sure image has enough slices if (qBallImageSize[1]<3 || qBallImageSize[2]<3 || qBallImageSize[3]<3) { MITK_INFO << "itkGibbsTrackingFilter: image size < 3 not supported"; m_AbortTracking = true; } // calculate rotation matrix vnl_matrix_fixed directionMatrix = m_ItkQBallImage->GetDirection().GetVnlMatrix(); vnl_vector_fixed d0 = directionMatrix.get_column(0); d0.normalize(); vnl_vector_fixed d1 = directionMatrix.get_column(1); d1.normalize(); vnl_vector_fixed d2 = directionMatrix.get_column(2); d2.normalize(); directionMatrix.set_column(0, d0); directionMatrix.set_column(1, d1); directionMatrix.set_column(2, d2); vnl_matrix_fixed I = directionMatrix*directionMatrix.transpose(); if(!I.is_identity(mitk::eps)){ MITK_INFO << "itkGibbsTrackingFilter: image direction is not a rotation matrix. Tracking not possible!"; m_AbortTracking = true; } // generate local working copy of image buffer int bufferSize = qBallImageSize[0]*qBallImageSize[1]*qBallImageSize[2]*qBallImageSize[3]; float* qBallImageBuffer = (float*) m_ItkQBallImage->GetBufferPointer(); float* workingQballImage = new float[bufferSize]; for (int i=0; i0 && i%qBallImageSize[0] == 0 && i>0) { sum /= qBallImageSize[0]; for (int j=i-qBallImageSize[0]; jGetBufferPointer(); maskImageSize[0] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(0); maskImageSize[1] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(1); maskImageSize[2] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(2); } else { mask = 0; maskImageSize[0] = qBallImageSize[1]; maskImageSize[1] = qBallImageSize[2]; maskImageSize[2] = qBallImageSize[3]; } int mask_oversamp_mult = maskImageSize[0]/qBallImageSize[1]; // load lookuptable QString applicationDir = QCoreApplication::applicationDirPath(); applicationDir.append("/"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); applicationDir.append("../"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); applicationDir.append("../../"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); std::string lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTBaryCoords.bin"); ifstream BaryCoords; BaryCoords.open(lutPath.c_str(), ios::in | ios::binary); float* coords; if (BaryCoords.is_open()) { float tmp; coords = new float [1630818]; BaryCoords.seekg (0, ios::beg); for (int i=0; i<1630818; i++) { BaryCoords.read((char *)&tmp, sizeof(tmp)); coords[i] = tmp; } BaryCoords.close(); } else { MITK_INFO << "itkGibbsTrackingFilter: unable to open barycoords file"; m_AbortTracking = true; } ifstream Indices; lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTIndices.bin"); Indices.open(lutPath.c_str(), ios::in | ios::binary); int* ind; if (Indices.is_open()) { int tmp; ind = new int [1630818]; Indices.seekg (0, ios::beg); for (int i=0; i<1630818; i++) { Indices.read((char *)&tmp, 4); ind[i] = tmp; } Indices.close(); } else { MITK_INFO << "itkGibbsTrackingFilter: unable to open indices file"; m_AbortTracking = true; } // initialize sphere interpolator with lookuptables SphereInterpolator *sinterp = new SphereInterpolator(coords, ind, QBALL_ODFSIZE, 301, 0.5); // get paramters float minSpacing; if(qBallImageSpacing[0]m_NumIt) { MITK_INFO << "itkGibbsTrackingFilter: not enough iterations!"; m_AbortTracking = true; } MITK_INFO << "itkGibbsTrackingFilter: steps: " << m_Steps; if (m_CurvatureHardThreshold < mitk::eps) m_CurvatureHardThreshold = 0; MITK_INFO << "itkGibbsTrackingFilter: curvature threshold: " << m_CurvatureHardThreshold; unsigned long singleIts = (unsigned long)((1.0*m_NumIt) / (1.0*m_Steps)); // setup metropolis hastings sampler MITK_INFO << "itkGibbsTrackingFilter: setting up MH-sampler"; if (m_Sampler!=NULL) delete m_Sampler; m_Sampler = new RJMCMC(NULL, 0, workingQballImage, qBallImageSize, qBallImageSpacing, cellsize); // setup energy computer MITK_INFO << "itkGibbsTrackingFilter: setting up Energy-computer"; EnergyComputer encomp(workingQballImage,qBallImageSize,qBallImageSpacing,sinterp,&(m_Sampler->m_ParticleGrid),mask,mask_oversamp_mult, directionMatrix); encomp.setParameters(m_ParticleWeight,m_ParticleWidth,m_ChempotConnection*m_ParticleLength*m_ParticleLength,m_ParticleLength,m_CurvatureHardThreshold,m_InexBalance,m_Chempot2, m_Meanval_sq); m_Sampler->SetEnergyComputer(&encomp); m_Sampler->SetParameters(m_TempStart,singleIts,m_ParticleLength,m_CurvatureHardThreshold,m_ChempotParticle); // main loop for( int step = 0; step < m_Steps; step++ ) { if (m_AbortTracking) break; m_CurrentStep = step+1; float temperature = m_TempStart * exp(alpha*(((1.0)*step)/((1.0)*m_Steps))); m_Sampler->SetTemperature(temperature); m_Sampler->Iterate(&m_ProposalAcceptance, &m_NumConnections, &m_NumParticles, &m_AbortTracking); MITK_INFO << "itkGibbsTrackingFilter: proposal acceptance: " << 100*m_ProposalAcceptance << "%"; MITK_INFO << "itkGibbsTrackingFilter: particles: " << m_NumParticles; MITK_INFO << "itkGibbsTrackingFilter: connections: " << m_NumConnections; MITK_INFO << "itkGibbsTrackingFilter: progress: " << 100*(float)step/m_Steps << "%"; if (m_BuildFibers) { int numPoints = m_Sampler->m_ParticleGrid.pcnt; float* points = new float[numPoints*m_Sampler->m_NumAttributes]; m_Sampler->WriteOutParticles(points); BuildFibers(points, numPoints); delete points; m_BuildFibers = false; } } int numPoints = m_Sampler->m_ParticleGrid.pcnt; float* points = new float[numPoints*m_Sampler->m_NumAttributes]; m_Sampler->WriteOutParticles(points); BuildFibers(points, numPoints); delete points; delete sinterp; delete coords; delete ind; delete workingQballImage; m_AbortTracking = true; m_BuildFibers = false; MITK_INFO << "itkGibbsTrackingFilter: done generate data"; } } diff --git a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h index 196556bc3c..bfc43e1b10 100644 --- a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h +++ b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h @@ -1,182 +1,197 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef itkGibbsTrackingFilter_h #define itkGibbsTrackingFilter_h #include "itkProcessObject.h" #include "itkVectorContainer.h" #include "itkImage.h" #include "GibbsTracking/pcRJMCMC.cpp" #include "GibbsTracking/auxilary_classes.cpp" #include #include #include #include #include #include #include namespace itk{ template< class TInputQBallImage, class TInputROIImage > class GibbsTrackingFilter : public ProcessObject{ public: typedef GibbsTrackingFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkNewMacro(Self); itkTypeMacro( GibbsTrackingFilter, ProcessObject ); /** Types for the DWI Input Image **/ typedef TInputQBallImage InputQBallImageType; /** Types for the Mask Image **/ typedef TInputROIImage MaskImageType; typedef typename MaskImageType::Pointer MaskImageTypePointer; typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType; typedef Image< float, 3 > GfaImageType; typedef typename GfaImageType::Pointer GfaImageTypePointer; itkSetMacro( TempStart, float ); itkGetMacro( TempStart, float ); itkSetMacro( TempEnd, float ); itkGetMacro( TempEnd, float ); itkSetMacro( NumIt, unsigned long ); itkGetMacro( NumIt, unsigned long ); itkSetMacro( ParticleWeight, float ); itkGetMacro( ParticleWeight, float ); /** width of particle sigma (std-dev of gaussian around center) **/ itkSetMacro( ParticleWidth, float ); itkGetMacro( ParticleWidth, float ); /** length of particle from midpoint to ends **/ itkSetMacro( ParticleLength, float ); itkGetMacro( ParticleLength, float ); itkSetMacro( ChempotConnection, float ); itkGetMacro( ChempotConnection, float ); itkSetMacro( ChempotParticle, float ); itkGetMacro( ChempotParticle, float ); itkSetMacro( InexBalance, float ); itkGetMacro( InexBalance, float ); itkSetMacro( Chempot2, float ); itkGetMacro( Chempot2, float ); itkSetMacro( FiberLength, int ); itkGetMacro( FiberLength, int ); itkSetMacro( AbortTracking, bool ); itkGetMacro( AbortTracking, bool ); itkSetMacro( CurrentStep, unsigned long ); itkGetMacro( CurrentStep, unsigned long ); itkSetMacro( SubtractMean, bool); itkGetMacro( SubtractMean, bool); itkSetMacro( CurvatureHardThreshold, float); itkGetMacro( CurvatureHardThreshold, float); /** Set/Get the Odf Input Image **/ itkSetInputMacro(OdfImage, InputQBallImageType, 0); itkGetInputMacro(OdfImage, InputQBallImageType, 0); /** Set/Get the Input mask image **/ itkSetMacro(MaskImage, MaskImageTypePointer); itkGetMacro(MaskImage, MaskImageTypePointer); itkSetMacro(GfaImage, GfaImageTypePointer); itkGetMacro(GfaImage, GfaImageTypePointer); itkGetMacro(NumParticles, unsigned long); itkGetMacro(NumConnections, unsigned long); itkGetMacro(NumAcceptedFibers, int); itkGetMacro(ProposalAcceptance, float); itkGetMacro(Steps, unsigned int); /** Entry Point For the Algorithm: Is invoked when Update() is called either directly or through itk pipeline propagation **/ void GenerateData(); /** override the Process Object Update because we don't have a dataobject as an outpgnome themeut. We can change this later by wrapping the tractcontainer in a dataobject decorator and letting the Superclass know about it. **/ struct StochasticTractGenerationCallbackStruct{ Pointer Filter; }; virtual void Update(){ this->GenerateData(); } FiberPolyDataType GetFiberBundle(); float GetMemoryUsage(); bool EstimateParticleWeight(); protected: GibbsTrackingFilter(); virtual ~GibbsTrackingFilter(); void ComputeFiberCorrelation(); void ComputeFiberCorrelationOriginal(); void BuildFibers(float* points, int numPoints); // Input Images typename InputQBallImageType::Pointer m_ItkQBallImage; typename MaskImageType::Pointer m_MaskImage; typename GfaImageType::Pointer m_GfaImage; // Tracking parameters float m_TempStart; // Start temperature float m_TempEnd; // End temperature unsigned long m_NumIt; // Total number of iterations unsigned long m_CurrentStep; // current tracking step float m_ParticleWeight; //w (unitless) float m_ParticleWidth; //sigma (mm) float m_ParticleLength; // ell (mm) float m_ChempotConnection; // gross L (chemisches potential) float m_ChempotParticle;// unbenutzt (immer null, wenn groesser dann insgesamt weniger teilchen) float m_InexBalance; // gewichtung zwischen den lambdas // -5 ... 5 -> nur intern ... nur extern,default 0 float m_Chempot2; // typischerweise 0, // korrektur fuer das geschaetzte integral int m_FiberLength; bool m_AbortTracking; bool m_SubtractMean; int m_NumAcceptedFibers; volatile bool m_BuildFibers; unsigned int m_Steps; float m_Memory; float m_ProposalAcceptance; float m_CurvatureHardThreshold; float m_Meanval_sq; RJMCMC* m_Sampler; FiberPolyDataType m_FiberPolyData; unsigned long m_NumParticles; unsigned long m_NumConnections; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkGibbsTrackingFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.h b/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.h index cc5ffbacaa..14eb005e8d 100644 --- a/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.h +++ b/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.h @@ -1,286 +1,301 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkStochasticTractographyFilter_h__ #define __itkStochasticTractographyFilter_h__ #include "itkImageToImageFilter.h" #include "vnl/vnl_random.h" #include "vnl/vnl_vector_fixed.h" #include "vnl/vnl_matrix.h" #include "itkArray.h" #include "itkVectorContainer.h" #include "vnl/algo/vnl_qr.h" #include "itkVariableLengthVector.h" #include "StochasticTracking/itkSlowPolyLineParametricPath.h" #include "itkSimpleFastMutexLock.h" #include "itkRealTimeClock.h" #include "itkDiffusionTensor3D.h" #include namespace itk{ /**Types for Probability Distribution **/ typedef Image< Array< double >, 3 > ProbabilityDistributionImageType; template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > class ITK_EXPORT StochasticTractographyFilter : public ImageToImageFilter< TInputDWIImage, TOutputConnectivityImage >{ public: typedef StochasticTractographyFilter Self; typedef ImageToImageFilter< TInputDWIImage, TOutputConnectivityImage > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkNewMacro(Self); itkTypeMacro( StochasticTractographyFilter, ImageToImageFilter ); /** Types for the DWI Input Image **/ typedef TInputDWIImage InputDWIImageType; /** Types for the Connectivity Output Image**/ typedef TOutputConnectivityImage OutputConnectivityImageType; /** Types for the Mask Image **/ typedef TInputWhiteMatterProbabilityImage InputWhiteMatterProbabilityImageType; /** Tract Types **/ typedef SlowPolyLineParametricPath< 3 > TractType; /** Types for the TractContainer **/ typedef VectorContainer< unsigned int, typename TractType::Pointer > TractContainerType; /** Types for Tensor Output Image **/ typedef Image< DiffusionTensor3D< double >, 3 > OutputTensorImageType; /** Types for the Image-wide Magnetic Field Gradient Directions **/ typedef VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > > GradientDirectionContainerType; /** Types for the Image-wide bValues **/ typedef double bValueType; typedef VectorContainer< unsigned int, bValueType > bValueContainerType; /** Types for the Measurement Frame of the Gradients **/ typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType; /** Type for the sample directions **/ typedef VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > > TractOrientationContainerType; /** the number of Tracts to generate **/ itkSetMacro( TotalTracts, unsigned int); itkGetMacro( TotalTracts, unsigned int); /** the maximum length of Tract **/ itkSetMacro( MaxTractLength, unsigned int ); itkGetMacro( MaxTractLength, unsigned int ); /** Set/Get bvalues **/ itkSetConstObjectMacro( bValues, bValueContainerType ); itkGetConstObjectMacro( bValues, bValueContainerType ); /** Set/Get of gradient directions **/ itkSetConstObjectMacro( Gradients, GradientDirectionContainerType ); itkGetConstObjectMacro( Gradients, GradientDirectionContainerType ); /** Set/Get the White Matter Probability Input image **/ /* At each voxel specifies the probability of a mylinated fiber existing at that location. This probability is interpreted to be the probability that a fiber tract passes through that region. */ itkSetInputMacro(WhiteMatterProbabilityImage, InputWhiteMatterProbabilityImageType, 1); itkGetInputMacro(WhiteMatterProbabilityImage, InputWhiteMatterProbabilityImageType, 1); //overide the built in set input function //we need to create a new cache everytime we change the input image //but we need to preserve it when the input image is the same void SetInput( typename InputDWIImageType::Pointer dwiimagePtr ){ Superclass::SetInput( dwiimagePtr ); //update the likelihood cache this->m_LikelihoodCachePtr = ProbabilityDistributionImageType::New(); this->m_LikelihoodCachePtr->CopyInformation( this->GetInput() ); this->m_LikelihoodCachePtr->SetBufferedRegion( this->GetInput()->GetBufferedRegion() ); this->m_LikelihoodCachePtr->SetRequestedRegion( this->GetInput()->GetRequestedRegion() ); this->m_LikelihoodCachePtr->Allocate(); this->m_CurrentLikelihoodCacheElements = 0; //update the likelihoodcache mutex image this->m_LikelihoodCacheMutexImagePtr = LikelihoodCacheMutexImageType::New(); this->m_LikelihoodCacheMutexImagePtr->CopyInformation( this->GetInput() ); this->m_LikelihoodCacheMutexImagePtr->SetBufferedRegion( this->GetInput()->GetBufferedRegion() ); this->m_LikelihoodCacheMutexImagePtr->SetRequestedRegion( this->GetInput()->GetRequestedRegion() ); this->m_LikelihoodCacheMutexImagePtr->Allocate(); } /** Set/Get the seed index **/ itkSetMacro( SeedIndex, typename InputDWIImageType::IndexType ); itkGetMacro( SeedIndex, typename InputDWIImageType::IndexType ); /** Set/Get the list of directions to sample **/ itkSetConstObjectMacro( SampleDirections, TractOrientationContainerType ); itkGetConstObjectMacro( SampleDirections, TractOrientationContainerType ); /** Set/Get the Measurement Frame **/ itkSetMacro( MeasurementFrame, MeasurementFrameType ); itkGetMacro( MeasurementFrame, MeasurementFrameType ); /** Set/Get the Maximum Likelihood Cache Size, the max num. of cached voxels **/ itkSetMacro( MaxLikelihoodCacheSize, unsigned int ); itkGetMacro( MaxLikelihoodCacheSize, unsigned int ); /** Get the Tracts that are generated **/ itkGetObjectMacro( OutputTractContainer, TractContainerType ); /** Get TensorImage **/ itkGetObjectMacro( OutputTensorImage, OutputTensorImageType ); void GenerateData(); void GenerateTractContainerOutput( void ); void GenerateTensorImageOutput( void ); protected: /** Convenience Types used only inside the filter **/ /**Types for the parameters of the Tensor Model **/ typedef vnl_vector_fixed< double, 7 > TensorModelParamType; /**Types for the parameters of the Constrained Model **/ typedef vnl_vector_fixed< double, 6 > ConstrainedModelParamType; /**Type to hold generated DWI values**/ typedef Image< VariableLengthVector< double >, 3 > DWIVectorImageType; /**Types for Probability Distribution **/ typedef Image< Array< double >, 3 > ProbabilityDistributionImageType; /** Types for the Image of Mutexes of the Likelihood distribution **/ typedef Image< SimpleFastMutexLock, 3 > LikelihoodCacheMutexImageType; StochasticTractographyFilter(); virtual ~StochasticTractographyFilter(); /** Load the default Sample Directions**/ void LoadDefaultSampleDirections( void ); /** Randomly chose a neighboring pixel weighted on distance **/ void ProbabilisticallyInterpolate( vnl_random& randomgenerator, const TractType::ContinuousIndexType& cindex, typename InputDWIImageType::IndexType& index); /** Functions and data related to fitting the tensor model at each pixel **/ void UpdateGradientDirections(void); void UpdateTensorModelFittingMatrices( void ); void CalculateTensorModelParameters( const DWIVectorImageType::PixelType& dwivalues, vnl_diag_matrix& W, TensorModelParamType& tensormodelparams); void CalculateConstrainedModelParameters( const TensorModelParamType& tensormodelparams, ConstrainedModelParamType& constrainedmodelparams); void CalculateNoiseFreeDWIFromConstrainedModel( const ConstrainedModelParamType& constrainedmodelparams, DWIVectorImageType::PixelType& noisefreedwi); void CalculateResidualVariance( const DWIVectorImageType::PixelType& noisydwi, const DWIVectorImageType::PixelType& noisefreedwi, const vnl_diag_matrix< double >& W, const unsigned int numberofparameters, double& residualvariance); void CalculateLikelihood( const DWIVectorImageType::PixelType &dwipixel, TractOrientationContainerType::ConstPointer orientations, ProbabilityDistributionImageType::PixelType& likelihood); void CalculatePrior( TractOrientationContainerType::Element v_prev, TractOrientationContainerType::ConstPointer orientations, ProbabilityDistributionImageType::PixelType& prior ); void CalculatePosterior( const ProbabilityDistributionImageType::PixelType& likelihood, const ProbabilityDistributionImageType::PixelType& prior, ProbabilityDistributionImageType::PixelType& posterior); void SampleTractOrientation( vnl_random& randomgenerator, const ProbabilityDistributionImageType::PixelType& posterior, TractOrientationContainerType::ConstPointer orientations, TractOrientationContainerType::Element& choosendirection ); void StochasticTractGeneration( typename InputDWIImageType::ConstPointer dwiimagePtr, typename InputWhiteMatterProbabilityImageType::ConstPointer maskimagePtr, typename InputDWIImageType::IndexType seedindex, unsigned long randomseed, TractType::Pointer tract ); /** Callback routine used by the threading library. This routine just calls the ThreadedGenerateData method after setting the correct region for this thread. **/ static ITK_THREAD_RETURN_TYPE StochasticTractGenerationCallback( void *arg ); struct StochasticTractGenerationCallbackStruct{ Pointer Filter; }; /** Thread Safe Function to check/update an entry in the likelihood cache **/ ProbabilityDistributionImageType::PixelType& AccessLikelihoodCache( typename InputDWIImageType::IndexType index ); /** Thread Safe Function to delegate a tract and obtain a randomseed to start tracking **/ bool DelegateTract(unsigned long& randomseed); /** Function to write a tract to the connectivity map **/ void TractContainerToConnectivityMap(TractContainerType::Pointer tractcontainer); /** Thread Safe Function to store a tract to a TractContainer **/ void StoreTract(TractType::Pointer tract); /** Randomly samples the existence of a fiber tract in the current voxel **/ bool FiberExistenceTest( vnl_random& randomgenerator, typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimage, typename InputWhiteMatterProbabilityImageType::IndexType index ); MeasurementFrameType m_MeasurementFrame; LikelihoodCacheMutexImageType::Pointer m_LikelihoodCacheMutexImagePtr; unsigned int m_TotalTracts; unsigned int m_MaxTractLength; GradientDirectionContainerType::ConstPointer m_Gradients; GradientDirectionContainerType::Pointer m_TransformedGradients; bValueContainerType::ConstPointer m_bValues; typename InputDWIImageType::IndexType m_SeedIndex; TractOrientationContainerType::ConstPointer m_SampleDirections; //these will be the same for every pixel in the image so //go ahead and do a QR decomposition to optimize the //LS fitting process for estimating the weighing matrix W //in this case we solve instead: //R*Beta = Q'logPhi vnl_matrix< double >* m_A; vnl_qr< double >* m_Aqr; ProbabilityDistributionImageType::Pointer m_LikelihoodCachePtr; unsigned long m_MaxLikelihoodCacheSize; //in Megabytes unsigned long m_MaxLikelihoodCacheElements; //in Elements (Voxels) unsigned long m_CurrentLikelihoodCacheElements; SimpleFastMutexLock m_LikelihoodCacheMutex; RealTimeClock::Pointer m_ClockPtr; unsigned int m_TotalDelegatedTracts; SimpleFastMutexLock m_TotalDelegatedTractsMutex; //unsigned long m_RandomSeed; SimpleFastMutexLock m_OutputImageMutex; TractContainerType::Pointer m_OutputTractContainer; SimpleFastMutexLock m_OutputTractContainerMutex; OutputTensorImageType::Pointer m_OutputTensorImage; vnl_random m_RandomGenerator; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkStochasticTractographyFilter.txx" #include "StochasticTracking/itkStochasticTractographyFilter_SD.txx" #endif #endif diff --git a/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.txx b/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.txx index 810d70b3c0..2f8f45cd71 100644 --- a/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.txx +++ b/Modules/DiffusionImaging/Tractography/itkStochasticTractographyFilter.txx @@ -1,685 +1,700 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkStochasticTractographyFilter.h" #include "vnl/vnl_math.h" #include "vnl/vnl_matrix_fixed.h" #include "vnl/vnl_vector_fixed.h" #include "vnl/vnl_matrix.h" #include "vnl/vnl_sym_matrix.h" #include "vnl/vnl_vector.h" #include "vnl/vnl_diag_matrix.h" #include "vnl/algo/vnl_qr.h" //#include "vnl/algo/vnl_svd.h" #include "vnl/algo/vnl_matrix_inverse.h" //#include "vnl/algo/vnl_symmetric_eigensystem.h" #include "itkSymmetricEigenAnalysis.h" #include "vnl/vnl_transpose.h" #include "itkVariableSizeMatrix.h" #include "itkPathIterator.h" #include "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" namespace itk{ template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::StochasticTractographyFilter(): m_TotalTracts(0),m_MaxTractLength(0),m_Gradients(NULL), m_TransformedGradients(NULL),m_bValues(NULL), m_SampleDirections(NULL), m_A(NULL), m_Aqr(NULL), m_LikelihoodCachePtr(NULL), m_MaxLikelihoodCacheSize(0), m_CurrentLikelihoodCacheElements(0), m_ClockPtr(NULL), m_TotalDelegatedTracts(0), m_OutputTractContainer(NULL){ this->m_SeedIndex[0]=0; this->m_SeedIndex[1]=0; this->m_SeedIndex[2]=0; this->m_MeasurementFrame.set_identity(); this->SetNumberOfRequiredInputs(2); //Filter needs a DWI image and a Mask Image m_ClockPtr = RealTimeClock::New(); this->m_RandomGenerator.reseed( ((unsigned long) this->m_ClockPtr->GetTimeStamp()) ); //load in default sample directions this->LoadDefaultSampleDirections(); } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::~StochasticTractographyFilter(){ delete this->m_A; delete this->m_Aqr; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::ProbabilisticallyInterpolate( vnl_random& randomgenerator, const TractType::ContinuousIndexType& cindex, typename InputDWIImageType::IndexType& index){ for(int i=0; i<3; i++){ if ((vcl_ceil(cindex[i]+vnl_math::eps)-cindex[i]) < randomgenerator.drand64()) index[i]=(int)vcl_ceil(cindex[i]); else index[i]=(int)vcl_floor(cindex[i]); } } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::UpdateGradientDirections(void){ //the gradient direction is transformed into IJK space //by moving into the image space and then to IJK space this->m_TransformedGradients = GradientDirectionContainerType::New(); unsigned int N = this->m_Gradients->Size(); for(unsigned int i=0; im_MeasurementFrame * this->m_Gradients->GetElement(i); /** The correction to LPS space is not neccessary as of itk 3.2 **/ //g_i[0] = -g_i[0]; //g_i[1] = -g_i[1]; g_i = this->GetInput()->GetDirection().GetInverse() * g_i; this->m_TransformedGradients->InsertElement(i, g_i); } } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::UpdateTensorModelFittingMatrices( void ){ //std::cout<<"UpdateTensorFittingMatrix\n"; //estimate the parameters using linear LS estimation //using convention specified by Salvador //solve for Beta in: logPhi=X*Beta //number of rows of the matrix depends on the number of inputs, //i.e. the number of measurements of the voxel (n) unsigned int N = this->m_TransformedGradients->Size(); if(this->m_A!=NULL) delete this->m_A; this->m_A = new vnl_matrix< double >(N, 7); //potential memory leak here vnl_matrix< double >& A = *(this->m_A); for(unsigned int j=0; j< N ; j++){ GradientDirectionContainerType::Element g = m_TransformedGradients->GetElement(j); const bValueType& b_i = m_bValues->GetElement(j); A(j,0)=1.0; A(j,1)=-1*b_i*(g[0]*g[0]); A(j,2)=-1*b_i*(g[1]*g[1]); A(j,3)=-1*b_i*(g[2]*g[2]); A(j,4)=-1*b_i*(2*g[0]*g[1]); A(j,5)=-1*b_i*(2*g[0]*g[2]); A(j,6)=-1*b_i*(2*g[1]*g[2]); } //Store a QR decomposition to quickly estimate //the weighing matrix for each voxel if(this->m_Aqr!=NULL) delete this->m_Aqr; this->m_Aqr = new vnl_qr< double >(A); //potential memory leak here } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculateTensorModelParameters( const DWIVectorImageType::PixelType& dwivalues, vnl_diag_matrix& W, TensorModelParamType& tensormodelparams){ unsigned int N = this->m_TransformedGradients->Size(); //setup const references for code clarity const vnl_matrix< double >& A = *(this->m_A); const vnl_qr< double >& Aqr = *(this->m_Aqr); //vnl_vector is used because the itk vector is limited in its methods and does not //contain an internal vnl class like VariableSizematrix //also itk_matrix has methods which are compatible with vnl_vectors vnl_vector< double > logPhi( N ); for(unsigned int j=0; j< N ; j++){ //fill up the logPhi vector using log(dwi) values logPhi.put(j, vcl_log(static_cast(dwivalues[j]) + vnl_math::eps)); } /** Find WLS estimate of the parameters of the Tensor model **/ // First estimate W by LS estimation of the intensities //vnl_matrix< double > Q = Aqr.Q(); //vnl_vector< double > QtB = Aqr.Q().transpose()*logPhi; //vnl_vector< double > QTB = Aqr.QtB(logPhi); //vnl_matrix< double > R = Aqr.R(); W = A* vnl_qr< double >(Aqr.R()).solve(Aqr.QtB(logPhi)); //W = A * Aqr.solve(logPhi); for(vnl_diag_matrix< double >::iterator i = W.begin();i!=W.end(); i++){ *i = vcl_exp( *i ); } // Now solve for parameters using the estimated weighing matrix tensormodelparams = vnl_qr< double >((W*A).transpose()*W*A).solve( (W*A).transpose()*W*logPhi); //int a; //tensormodelparams = vnl_qr< double >((W*A)).solve(W*logPhi); } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculateConstrainedModelParameters( const TensorModelParamType& tensormodelparams, ConstrainedModelParamType& constrainedmodelparams){ vnl_sym_matrix< double > D( 3, 0 ); double alpha =0; double beta=0; //set the tensor model parameters into a Diffusion tensor D(0,0) = tensormodelparams[1]; D(0,1) = tensormodelparams[4]; D(0,2) = tensormodelparams[5]; D(1,0) = tensormodelparams[4]; D(1,1) = tensormodelparams[2]; D(1,2) = tensormodelparams[6]; D(2,0) = tensormodelparams[5]; D(2,1) = tensormodelparams[6]; D(2,2) = tensormodelparams[3]; //pass through the no gradient intensity Z_0 and //calculate alpha, beta and v hat (the eigenvector //associated with the largest eigenvalue) vnl_matrix_fixed< double, 3, 3 > S(0.0); vnl_vector_fixed< double, 3 > Lambda(0.0); SymmetricEigenAnalysis< vnl_sym_matrix< double >, vnl_vector_fixed< double, 3 >, vnl_matrix_fixed< double, 3, 3 > > eigensystem( 3 ); eigensystem.ComputeEigenValuesAndVectors( D, Lambda, S ); //need to take abs to get rid of negative eigenvalues alpha = (vcl_abs(Lambda[0]) + vcl_abs(Lambda[1])) / 2; beta = vcl_abs(Lambda[2]) - alpha; constrainedmodelparams[0] = tensormodelparams[0]; constrainedmodelparams[1] = alpha; constrainedmodelparams[2] = beta; constrainedmodelparams[3] = S[2][0]; constrainedmodelparams[4] = S[2][1]; constrainedmodelparams[5] = S[2][2]; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculateNoiseFreeDWIFromConstrainedModel( const ConstrainedModelParamType& constrainedmodelparams, DWIVectorImageType::PixelType& noisefreedwi){ unsigned int N = this->m_TransformedGradients->Size(); const double& z_0 = constrainedmodelparams[0]; const double& alpha = constrainedmodelparams[1]; const double& beta = constrainedmodelparams[2]; TractOrientationContainerType::Element v_hat( constrainedmodelparams[3], constrainedmodelparams[4], constrainedmodelparams[5]); for(unsigned int i=0; i < N ; i++ ){ const double& b_i = this->m_bValues->GetElement(i); const GradientDirectionContainerType::Element& g_i = this->m_TransformedGradients->GetElement(i); noisefreedwi.SetElement(i, vcl_exp(z_0-(alpha*b_i+beta*b_i*vnl_math_sqr(dot_product(g_i, v_hat))))); } } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculateResidualVariance( const DWIVectorImageType::PixelType& noisydwi, const DWIVectorImageType::PixelType& noisefreedwi, const vnl_diag_matrix< double >& W, const unsigned int numberofparameters, double& residualvariance){ unsigned int N = this->m_TransformedGradients->Size(); residualvariance=0; /** Not sure if we should be taking difference of log or nonlog intensities **/ /** residual variance is too low if we take the difference of log intensities **/ /** perhaps using WLS will correct this problem **/ for(unsigned int i=0; i void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculateLikelihood( const DWIVectorImageType::PixelType &dwipixel, TractOrientationContainerType::ConstPointer orientations, ProbabilityDistributionImageType::PixelType& likelihood){ unsigned int N = this->m_TransformedGradients->Size(); TensorModelParamType tensorparams( 0.0 ); vnl_diag_matrix< double > W(N,0); ConstrainedModelParamType constrainedparams( 0.0 ); DWIVectorImageType::PixelType noisefreedwi(N); double residualvariance=0; double jointlikelihood=1; CalculateTensorModelParameters( dwipixel, W, tensorparams ); CalculateConstrainedModelParameters( tensorparams, constrainedparams ); CalculateNoiseFreeDWIFromConstrainedModel( constrainedparams, noisefreedwi ); CalculateResidualVariance( dwipixel, noisefreedwi, W, 6, residualvariance ); for(unsigned int i=0; i < orientations->Size(); i++){ /** Vary the entry corresponding to the estimated Tract orientation over the selected sample directions, while preserving the best estimate for the other parameters **/ TractOrientationContainerType::Element currentdir = orientations->GetElement(i); /** Incorporate the current sample direction into the secondary parameters **/ constrainedparams[3]=currentdir[0]; constrainedparams[4]=currentdir[1]; constrainedparams[5]=currentdir[2]; /** Obtain the estimated intensity for this choice of Tract direction **/ CalculateNoiseFreeDWIFromConstrainedModel(constrainedparams, noisefreedwi); jointlikelihood = 1.0; for(unsigned int j=0; j void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculatePrior( TractOrientationContainerType::Element v_prev, TractOrientationContainerType::ConstPointer orientations, ProbabilityDistributionImageType::PixelType& prior ){ const double gamma = 1; for(unsigned int i=0; i < orientations->Size(); i++){ if(v_prev.squared_magnitude()==0){ prior[i]=1.0; } else{ prior[i] = dot_product(orientations->GetElement(i),v_prev);; if(prior[i]<0){ prior[i]=0; } else{ prior[i]=vcl_pow(prior[i],gamma); } } } } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::CalculatePosterior( const ProbabilityDistributionImageType::PixelType& likelihood, const ProbabilityDistributionImageType::PixelType& prior, ProbabilityDistributionImageType::PixelType& posterior){ double sum=0; for(unsigned int i=0; i void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::SampleTractOrientation( vnl_random& randomgenerator, const ProbabilityDistributionImageType::PixelType& posterior, TractOrientationContainerType::ConstPointer orientations, TractOrientationContainerType::Element& choosendirection ){ double randomnum = randomgenerator.drand64(); int i=0; double cumsum=0; //will crash in the unlikely case that 0 was choosen as the randomnum while(cumsum < randomnum){ cumsum+=posterior[i]; i++; } choosendirection = orientations->GetElement(i-1); //std::cout<< "cumsum: " << cumsum< bool StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::FiberExistenceTest( vnl_random& randomgenerator, typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimage, typename InputWhiteMatterProbabilityImageType::IndexType index ){ double randomnum = randomgenerator.drand64(); if( randomnum < wmpimage->GetPixel( index ) ) return true; else return false; } //the seedindex is in continuous IJK coordinates template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::StochasticTractGeneration( typename InputDWIImageType::ConstPointer dwiimagePtr, typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimagePtr, typename InputDWIImageType::IndexType seedindex, unsigned long randomseed, TractType::Pointer tract){ TractType::ContinuousIndexType cindex_curr = seedindex; typename InputDWIImageType::IndexType index_curr = {{0,0,0}}; ProbabilityDistributionImageType::PixelType prior_curr(this->m_SampleDirections->Size()); ProbabilityDistributionImageType::PixelType posterior_curr(this->m_SampleDirections->Size()); TractOrientationContainerType::Element v_curr(0,0,0); TractOrientationContainerType::Element v_prev(0,0,0); tract->Initialize(); vnl_random randomgenerator(randomseed); //std::cout<m_MaxTractLength; j++){ this->ProbabilisticallyInterpolate( randomgenerator, cindex_curr, index_curr ); if(!dwiimagePtr->GetLargestPossibleRegion().IsInside(index_curr)){ break; } if( FiberExistenceTest( randomgenerator, wmpimagePtr, index_curr ) ){ tract->AddVertex(cindex_curr); this->CalculatePrior( v_prev, this->m_SampleDirections, prior_curr); const ProbabilityDistributionImageType::PixelType& cachelikelihood_curr = this->AccessLikelihoodCache(index_curr); if( cachelikelihood_curr.GetSize() != 0){ //use the cached direction this->CalculatePosterior( cachelikelihood_curr, prior_curr, posterior_curr); } else{ //do the likelihood calculation and discard //std::cout<<"Cache Miss!\n"; ProbabilityDistributionImageType::PixelType likelihood_curr_temp(this->m_SampleDirections->Size()); this->CalculateLikelihood(static_cast< DWIVectorImageType::PixelType >( dwiimagePtr->GetPixel(index_curr)), this->m_SampleDirections, likelihood_curr_temp); this->CalculatePosterior( likelihood_curr_temp, prior_curr, posterior_curr); } this->SampleTractOrientation(randomgenerator, posterior_curr, this->m_SampleDirections, v_curr); //takes into account voxels of different sizes //converts from a step length of 1 mm to the corresponding length in IJK space const typename InputDWIImageType::SpacingType& spacing = dwiimagePtr->GetSpacing(); cindex_curr[0]+=v_curr[0]/spacing[0]; cindex_curr[1]+=v_curr[1]/spacing[1]; cindex_curr[2]+=v_curr[2]/spacing[2]; v_prev=v_curr; } else{ //fiber doesn't exist in this voxel //std::cout<<"Stopped Tracking: No Fiber in this Voxel\n"; break; } } } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::GenerateTractContainerOutput(){ //allocate tractcontainer this->m_OutputTractContainer = TractContainerType::New(); this->UpdateGradientDirections(); this->UpdateTensorModelFittingMatrices(); this->m_TotalDelegatedTracts = 0; //calculate the number of voxels to cache from Megabyte memory size limit ProbabilityDistributionImageType::PixelType element(this->GetSampleDirections()->Size()); unsigned long elementsize = sizeof(ProbabilityDistributionImageType::PixelType) + sizeof(double)*element.Size(); this->m_MaxLikelihoodCacheElements = (this->m_MaxLikelihoodCacheSize*1048576)/elementsize; std::cout << "MaxLikelhoodCacheElements: " << this->m_MaxLikelihoodCacheElements << std::endl; //setup the multithreader StochasticTractGenerationCallbackStruct data; data.Filter = this; this->GetMultiThreader()->SetSingleMethod( StochasticTractGenerationCallback, &data ); this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads()); std::cout<<"Number of Threads: " << this->GetMultiThreader()->GetNumberOfThreads() << std::endl; //start the multithreaded execution this->GetMultiThreader()->SingleMethodExecute(); std::cout<< "CurrentLikelihoodCacheElements: " << this->m_CurrentLikelihoodCacheElements << std::endl; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::GenerateData(){ //Generate the tracts this->GenerateTractContainerOutput(); //allocate outputs this->AllocateOutputs(); //write tracts to output image this->TractContainerToConnectivityMap(this->m_OutputTractContainer); } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > ITK_THREAD_RETURN_TYPE StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::StochasticTractGenerationCallback( void *arg ) { StochasticTractGenerationCallbackStruct* str= (StochasticTractGenerationCallbackStruct *) (((MultiThreader::ThreadInfoStruct *)(arg))->UserData); typename InputDWIImageType::ConstPointer inputDWIImagePtr = str->Filter->GetInput(); typename InputWhiteMatterProbabilityImageType::ConstPointer inputWMPImage = str->Filter->GetWhiteMatterProbabilityImageInput(); unsigned long randomseed=0; while(str->Filter->DelegateTract(randomseed)){ //std::cout<Filter->StochasticTractGeneration( inputDWIImagePtr, inputWMPImage, str->Filter->GetSeedIndex(), randomseed, tract); //only store tract if it is of nonzero length if( tract->GetVertexList()->Size() > 4 ){ //std::cout<<"Storing tract\n"; str->Filter->StoreTract(tract); } else{ //std::cout<<"Not Storing Tract\n"; } } return ITK_THREAD_RETURN_VALUE; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > ProbabilityDistributionImageType::PixelType& StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::AccessLikelihoodCache( typename InputDWIImageType::IndexType index ) { this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Lock(); ProbabilityDistributionImageType::PixelType& likelihood = m_LikelihoodCachePtr->GetPixel( index ); typename InputDWIImageType::ConstPointer inputDWIImagePtr = this->GetInput(); if( likelihood.GetSize() !=0){ //entry found in cache this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock(); return likelihood; } //we need to lock m_CurrentLikelihoodCacheElements as well but not crucial right now else if( this->m_CurrentLikelihoodCacheElements < this->m_MaxLikelihoodCacheElements ){ //entry not found in cache but we have space to store it likelihood.SetSize(this->m_SampleDirections->Size()); this->CalculateLikelihood(static_cast< DWIVectorImageType::PixelType >( inputDWIImagePtr->GetPixel(index)), this->m_SampleDirections, likelihood); this->m_CurrentLikelihoodCacheElements++; this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock(); return likelihood; } else{ //entry not found in cache and no space to store it this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock(); return likelihood; } this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock(); // dummy return likelihood; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > bool StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::DelegateTract(unsigned long& randomseed){ bool success = false; this->m_TotalDelegatedTractsMutex.Lock(); if(this->m_TotalDelegatedTracts < this->m_TotalTracts){ randomseed = this->m_RandomGenerator.lrand32(); this->m_TotalDelegatedTracts++; success = true; //a tract was successfully delegated } else success = false; //all tracts have been delegated this->m_TotalDelegatedTractsMutex.Unlock(); return success; } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::TractContainerToConnectivityMap(TractContainerType::Pointer tractcontainer){ //zero the output image typename OutputConnectivityImageType::Pointer outputPtr = this->GetOutput(); outputPtr->FillBuffer(0); typedef PathIterator< OutputConnectivityImageType, TractType > OutputTractIteratorType; for(unsigned int i=0; iSize(); i++ ){ TractType::Pointer tract = tractcontainer->GetElement(i); //std::cout<< tract->EndOfInput() < void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::StoreTract(TractType::Pointer tract){ this->m_OutputTractContainerMutex.Lock(); this->m_OutputTractContainer->InsertElement( this->m_OutputTractContainer->Size(), tract); this->m_OutputTractContainerMutex.Unlock(); } template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage > void StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage > ::GenerateTensorImageOutput(void){ this->UpdateGradientDirections(); this->UpdateTensorModelFittingMatrices(); //allocate the tensor image this->m_OutputTensorImage = OutputTensorImageType::New(); m_OutputTensorImage->CopyInformation( this->GetInput() ); m_OutputTensorImage->SetBufferedRegion( this->GetInput()->GetBufferedRegion() ); m_OutputTensorImage->SetRequestedRegion( this->GetInput()->GetRequestedRegion() ); m_OutputTensorImage->Allocate(); //define an iterator for the input and output images typedef itk::ImageRegionConstIterator< InputDWIImageType > DWIImageIteratorType; typedef itk::ImageRegionIterator< OutputTensorImageType > TensorImageIteratorType; DWIImageIteratorType inputDWIit( this->GetInput(), m_OutputTensorImage->GetRequestedRegion() ); TensorImageIteratorType outputtensorit ( m_OutputTensorImage, m_OutputTensorImage->GetRequestedRegion() ); unsigned int N = this->m_TransformedGradients->Size(); TensorModelParamType tensormodelparams( 0.0 ); vnl_diag_matrix< double > W(N,0); for(inputDWIit.GoToBegin(), outputtensorit.GoToBegin(); !outputtensorit.IsAtEnd(); ++inputDWIit, ++outputtensorit){ CalculateTensorModelParameters( inputDWIit.Get(), W, tensormodelparams); OutputTensorImageType::PixelType& D = outputtensorit.Value(); //set the tensor model parameters into a Diffusion tensor D(0,0) = tensormodelparams[1]; D(0,1) = tensormodelparams[4]; D(0,2) = tensormodelparams[5]; D(1,0) = tensormodelparams[4]; D(1,1) = tensormodelparams[2]; D(1,2) = tensormodelparams[6]; D(2,0) = tensormodelparams[5]; D(2,1) = tensormodelparams[6]; D(2,2) = tensormodelparams[3]; //std::cout< DWI IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageReader.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageIOFactory.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriterFactory.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSerializer.cpp # DataStructures -> QBall IODataStructures/QBallImages/mitkQBallImageSource.cpp IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriter.cpp IODataStructures/QBallImages/mitkNrrdQBallImageIOFactory.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriterFactory.cpp IODataStructures/QBallImages/mitkQBallImage.cpp IODataStructures/QBallImages/mitkQBallImageSerializer.cpp # DataStructures -> Tensor IODataStructures/TensorImages/mitkTensorImageSource.cpp IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp IODataStructures/TensorImages/mitkNrrdTensorImageIOFactory.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriterFactory.cpp IODataStructures/TensorImages/mitkTensorImage.cpp IODataStructures/TensorImages/mitkTensorImageSerializer.cpp # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriter.cpp IODataStructures/FiberBundleX/mitkFiberBundleXReader.cpp IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.cpp IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp # DataStructures -> PlanarFigureComposite IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp # DataStructures -> Tbss IODataStructures/TbssImages/mitkTbssImageSource.cpp IODataStructures/TbssImages/mitkTbssRoiImageSource.cpp IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssImageIOFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageIOFactory.cpp IODataStructures/TbssImages/mitkTbssImage.cpp IODataStructures/TbssImages/mitkTbssRoiImage.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriterFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriterFactory.cpp IODataStructures/TbssImages/mitkTbssImporter.cpp # DataStructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkCompositeMapper.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp Rendering/mitkFiberBundleXMapper2D.cpp Rendering/mitkFiberBundleXMapper3D.cpp Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp Rendering/mitkTbssImageMapper.cpp Rendering/mitkPlanarCircleMapper3D.cpp Rendering/mitkPlanarPolygonMapper3D.cpp Rendering/mitkConnectomicsNetworkMapper3D.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp Algorithms/mitkTractAnalyzer.cpp # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp # Tractography Tractography/itkStochasticTractographyFilter.h + + # Function Collection + mitkDiffusionFunctionCollection.cpp + ) set(H_FILES + # function Collection + mitkDiffusionFunctionCollection.h + # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkTbssImageMapper.h Rendering/mitkOdfVtkMapper2D.h Rendering/mitkFiberBundleXMapper3D.h Rendering/mitkFiberBundleXMapper2D.h Rendering/mitkFiberBundleXThreadMonitorMapper3D.h Rendering/mitkPlanarCircleMapper3D.h Rendering/mitkPlanarPolygonMapper3D.h Rendering/mitkConnectomicsNetworkMapper3D.h # Reconstruction Reconstruction/itkDiffusionQballReconstructionImageFilter.h Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h + Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h Reconstruction/itkPointShell.h Reconstruction/itkOrientationDistributionFunction.h Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h Reconstruction/itkRegularizedIVIMLocalVariationImageFilter.h Reconstruction/itkRegularizedIVIMReconstructionFilter.h Reconstruction/itkRegularizedIVIMReconstructionSingleIteration.h # IO Datastructures IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h IODataStructures/TbssImages/mitkTbssImporter.h # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.h IODataStructures/FiberBundleX/mitkFiberBundleXWriter.h IODataStructures/FiberBundleX/mitkFiberBundleXReader.h IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.h IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h # Datastructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h # Tractography Tractography/itkGibbsTrackingFilter.h Tractography/itkStochasticTractographyFilter.h # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkB0ImageExtractionToSeparateImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkSkeletonizationFilter.h Algorithms/itkReduceDirectionGradientsFilter.h Algorithms/itkResidualImageFilter.h Algorithms/itkExtractChannelFromRgbaImageFilter.h # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h Algorithms/Connectomics/mitkConnectomicsHistogramBase.h Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h Algorithms/Connectomics/mitkConnectomicsHistogramCache.h Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h ) set( TOOL_FILES ) if(WIN32) endif(WIN32) #MITK_MULTIPLEX_PICTYPE( Algorithms/mitkImageRegistrationMethod-TYPE.cpp ) diff --git a/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.cpp b/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.cpp new file mode 100644 index 0000000000..4db8e9705a --- /dev/null +++ b/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.cpp @@ -0,0 +1,105 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkDiffusionFunctionCollection.h" +#include +#include "mitkVector.h" + +// for Windows +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// Namespace ::SH +#include +#include +#include + +// Namespace ::vnl_function +//#include "vnl/vnl_vector.h" + +//------------------------- SH-function ------------------------------------ + +double mitk::sh::factorial(int number) { + if(number <= 1) return 1; + double result = 1.0; + for(int i=1; i<=number; i++) + result *= i; + return result; +} + +void mitk::sh::Cart2Sph(double x, double y, double z, double *cart) +{ + double phi, th, rad; + rad = sqrt(x*x+y*y+z*z); + if( rad < mitk::eps ) + { + th = M_PI/2; + phi = M_PI/2; + } + else + { + th = acos(z/rad); + phi = atan2(y, x); + } + cart[0] = phi; + cart[1] = th; + cart[2] = rad; +} + +double mitk::sh::legendre0(int l) +{ + if( l%2 != 0 ) + { + return 0; + } + else + { + double prod1 = 1.0; + for(int i=1;i +vnl_vector mitk::vnl_function::element_cast (vnl_vector const& v1) +{ + vnl_vector result(v1.size()); + + for(int i = 0 ; i < v1.size(); i++) + result[i] = static_cast(v1[i]); + + return result; +} diff --git a/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.h b/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.h new file mode 100644 index 0000000000..2c517178b1 --- /dev/null +++ b/Modules/DiffusionImaging/mitkDiffusionFunctionCollection.h @@ -0,0 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __mitkDiffusionFunctionCollection_h_ +#define __mitkDiffusionFunctionCollection_h_ + +template +class vnl_vector; + +namespace mitk{ + +namespace sh +{ + +double factorial(int number); +void Cart2Sph(double x, double y, double z, double* cart); +double legendre0(int l); +double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart); +double Yj(int m, int k, double theta, double phi); + +} + +namespace vnl_function +{ + +template +vnl_vector element_cast (vnl_vector const& v1); + +} +} + +#endif //__mitkDiffusionFunctionCollection_h_ + diff --git a/Modules/GraphAlgorithms/itkShortestPathCostFunction.h b/Modules/GraphAlgorithms/itkShortestPathCostFunction.h index 07803ad5b7..733fdb537e 100644 --- a/Modules/GraphAlgorithms/itkShortestPathCostFunction.h +++ b/Modules/GraphAlgorithms/itkShortestPathCostFunction.h @@ -1,82 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathCostFunction_h #define __itkShortestPathCostFunction_h #include "itkObject.h" #include "itkObjectFactory.h" #include "itkShapedNeighborhoodIterator.h" #include namespace itk { // \brief this is a pure virtual superclass for all cost function for the itkShortestPathImageFilter template class ShortestPathCostFunction : public Object { public: /** Standard class typedefs. */ typedef ShortestPathCostFunction Self; typedef Object Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ShapedNeighborhoodIterator< TInputImageType > itkShapedNeighborhoodIteratorType; - + /** Run-time type information (and related methods). */ itkTypeMacro(ShortestPathCostFunction, Object); /** Type definition for the input image. */ typedef TInputImageType ImageType; // More typdefs for convenience typedef typename TInputImageType::Pointer ImagePointer; typedef typename TInputImageType::ConstPointer ImageConstPointer; typedef typename TInputImageType::PixelType PixelType; typedef typename TInputImageType::IndexType IndexType; /** Set the input image. */ itkSetConstObjectMacro(Image,TInputImageType); // \brief calculates the costs for going from pixel1 to pixel2 virtual double GetCost( IndexType p1, IndexType p2) = 0; // \brief returns the minimal costs possible (needed for A*) virtual double GetMinCost() = 0; // \brief Initialize the metric virtual void Initialize () = 0; // \brief Set Starpoint for Path void SetStartIndex (const IndexType & StartIndex); // \brief Set Endpoint for Path void SetEndIndex(const IndexType & EndIndex); ShortestPathCostFunction(); protected: virtual ~ShortestPathCostFunction() {}; void PrintSelf(std::ostream& os, Indent indent) const; ImageConstPointer m_Image; IndexType m_StartIndex, m_EndIndex; private: ShortestPathCostFunction(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } // end namespace itk #include "itkShortestPathCostFunction.txx" #endif /* __itkShortestPathCostFunction_h */ diff --git a/Modules/GraphAlgorithms/itkShortestPathCostFunction.txx b/Modules/GraphAlgorithms/itkShortestPathCostFunction.txx index 5ff61dbf3a..48572b7460 100644 --- a/Modules/GraphAlgorithms/itkShortestPathCostFunction.txx +++ b/Modules/GraphAlgorithms/itkShortestPathCostFunction.txx @@ -1,49 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathCostFunction_cpp #define __itkShortestPathCostFunction_cpp namespace itk { // Constructor template ShortestPathCostFunction ::ShortestPathCostFunction() { } template void ShortestPathCostFunction ::PrintSelf( std::ostream& os, Indent indent ) const { Superclass::PrintSelf(os,indent); } template void ShortestPathCostFunction:: SetStartIndex (const typename TInputImageType::IndexType &StartIndex) { for (unsigned int i=0;i void ShortestPathCostFunction:: SetEndIndex (const typename TInputImageType::IndexType &EndIndex) { for (unsigned int i=0;i #include namespace itk { template class ShortestPathCostFunctionTbss : public ShortestPathCostFunction { public: /** Standard class typedefs. */ typedef ShortestPathCostFunctionTbss Self; typedef ShortestPathCostFunction Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef itk::ImageRegionConstIterator ConstIteratorType; typedef typename TInputImageType::IndexType IndexType; typedef itk::Image FloatImageType; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Run-time type information (and related methods). */ itkTypeMacro(Self, Superclass); // \brief calculates the costs for going from p1 to p2 virtual double GetCost( IndexType p1, IndexType p2); // \brief Initialize the metric virtual void Initialize (); // \brief returns the minimal costs possible (needed for A*) virtual double GetMinCost(); void SetThreshold(double t) { m_Threshold = t; } protected: ShortestPathCostFunctionTbss(); virtual ~ShortestPathCostFunctionTbss() {}; double m_Threshold; private: }; } // end namespace itk #include "itkShortestPathCostFunctionTbss.txx" #endif /* __itkShortestPathCostFunctionTbss_h */ diff --git a/Modules/GraphAlgorithms/itkShortestPathCostFunctionTbss.txx b/Modules/GraphAlgorithms/itkShortestPathCostFunctionTbss.txx index 88d70092ad..2e301981e9 100644 --- a/Modules/GraphAlgorithms/itkShortestPathCostFunctionTbss.txx +++ b/Modules/GraphAlgorithms/itkShortestPathCostFunctionTbss.txx @@ -1,73 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathCostFunctionTbss_cpp #define __itkShortestPathCostFunctionTbss_cpp #include namespace itk { // Constructor template ShortestPathCostFunctionTbss ::ShortestPathCostFunctionTbss() { } template double ShortestPathCostFunctionTbss ::GetCost(IndexType p1 ,IndexType p2) { // Very simple Metric: // The squared difference of both values is defined as cost double a,b,c; ConstIteratorType it( this->m_Image, this->m_Image->GetRequestedRegion()); it.SetIndex(p1); a = it.Get(); it.SetIndex(p2); b = it.Get(); if(this->m_Image->GetPixel(p2) < m_Threshold) { c = std::numeric_limits::max( ); } else { double dxSqt = (p1[0]-p2[0]) * (p1[0]-p2[0]);// * (p1[0]-p2[0]); double dySqt = (p1[1]-p2[1]) * (p1[1]-p2[1]); double dzSqt = (p1[2]-p2[2]) * (p1[2]-p2[2]); double weight = this->m_Image->GetPixel(p2); c = (dxSqt + dySqt + dzSqt) + 10000 * (1-weight); } return c; } template void ShortestPathCostFunctionTbss ::Initialize() { } template double ShortestPathCostFunctionTbss ::GetMinCost() { return 1; } } // end namespace itk #endif // __itkShortestPathCostFunctionSimple_txx diff --git a/Modules/GraphAlgorithms/itkShortestPathImageFilter.h b/Modules/GraphAlgorithms/itkShortestPathImageFilter.h index 266e84ec3c..3f1359b17a 100644 --- a/Modules/GraphAlgorithms/itkShortestPathImageFilter.h +++ b/Modules/GraphAlgorithms/itkShortestPathImageFilter.h @@ -1,210 +1,225 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathImageFilter_h #define __itkShortestPathImageFilter_h #include "itkImageToImageFilter.h" #include "itkShortestPathCostFunction.h" #include "itkShortestPathNode.h" #include #include // ------- INFORMATION ---------- /// SET FUNCTIONS //void SetInput( ItkImage ) // Compulsory //void SetStartIndex (const IndexType & StartIndex); // Compulsory //void SetEndIndex(const IndexType & EndIndex); // Compulsory //void SetFullNeighborsMode(bool) // Optional (default=false), if false N4, if true N26 //void SetActivateTimeOut(bool) // Optional (default=false), for debug issues: after 30s algorithms terminates. You can have a look at the VectorOrderImage to see how far it came //void SetMakeOutputImage(bool) // Optional (default=true), Generate an outputimage of the path. You can also get the path directoy with GetVectorPath() //void SetCalcAllDistances(bool) // Optional (default=false), Calculate Distances over the whole image. CAREFUL, algorithm time extends a lot. Necessary for GetDistanceImage //void SetStoreVectorOrder(bool) // Optional (default=false), Stores in which order the pixels were checked. Necessary for GetVectorOrderImage //void AddEndIndex(const IndexType & EndIndex) //Optional. By calling this function you can add several endpoints! The algorithm will look for several shortest Pathes. From Start to all Endpoints. // /// GET FUNCTIONS //std::vector< itk::Index<3> > GetVectorPath(); // returns the shortest path as vector //std::vector< std::vector< itk::Index<3> > GetMultipleVectorPathe(); // returns a vector of shortest Pathes (which are vectors of points) //GetDistanceImage // Returns the distance image //GetVectorOrderIMage // Returns the Vector Order image // // EXAMPLE USE // pleae see qmitkmitralvalvesegmentation4dtee bundle namespace itk { template class ShortestPathImageFilter : public ImageToImageFilter { public: //Standard Typedefs - typedef ShortestPathImageFilter Self; + typedef ShortestPathImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; // Typdefs for metric - typedef ShortestPathCostFunction< TInputImageType > CostFunctionType; - typedef typename CostFunctionType::Pointer CostFunctionTypePointer; + typedef ShortestPathCostFunction< TInputImageType > CostFunctionType; + typedef typename CostFunctionType::Pointer CostFunctionTypePointer; // More typdefs for convenience typedef TInputImageType InputImageType; typedef typename TInputImageType::Pointer InputImagePointer; typedef typename TInputImageType::PixelType InputImagePixelType; typedef typename TInputImageType::SizeType InputImageSizeType; typedef typename TInputImageType::IndexType IndexType; typedef typename itk::ImageRegionIteratorWithIndex< InputImageType > InputImageIteratorType; typedef TOutputImageType OutputImageType; typedef typename TOutputImageType::Pointer OutputImagePointer; typedef typename TOutputImageType::PixelType OutputImagePixelType; typedef typename TOutputImageType::IndexType OutputImageIndexType; typedef ImageRegionIteratorWithIndex< OutputImageType > OutputImageIteratorType; typedef itk::ShapedNeighborhoodIterator< TInputImageType > itkShapedNeighborhoodIteratorType; // New Macro for smartpointer instantiation itkNewMacro(Self) // Run-time type information itkTypeMacro(ShortestPathImageFilter, ImageToImageFilter) // Display void PrintSelf( std::ostream& os, Indent indent ) const; // Compare function for A_STAR struct CompareNodeStar { bool operator()(ShortestPathNode *a, ShortestPathNode *b) { return (a->distAndEst > b->distAndEst); } }; // \brief Set Starpoint for ShortestPath Calculation void SetStartIndex (const IndexType & StartIndex); // \brief Adds Endpoint for multiple ShortestPath Calculation void AddEndIndex (const IndexType & index); // \brief Set Endpoint for ShortestPath Calculation void SetEndIndex(const IndexType & EndIndex); // \brief Set FullNeighborsMode. false = no diagonal neighbors, in 2D this means N4 Neigborhood. true = would be N8 in 2D itkSetMacro (FullNeighborsMode, bool); itkGetMacro (FullNeighborsMode, bool); // \brief (default=true), Produce output image, which shows the shortest path. But you can also get the shortest Path directly as vector with the function GetVectorPath itkSetMacro (MakeOutputImage, bool); itkGetMacro (MakeOutputImage, bool); // \brief (default=false), Store an Vector of Order, so you can call getVectorOrderImage after update itkSetMacro (StoreVectorOrder, bool); itkGetMacro (StoreVectorOrder, bool); // \brief (default=false), // Calculate all Distances to all pixels, so you can call getDistanceImage after update (warning algo will take a long time) itkSetMacro (CalcAllDistances, bool); itkGetMacro (CalcAllDistances, bool); // \brief (default=false), for debug issues: after 30s algorithms terminates. You can have a look at the VectorOrderImage to see how far it came itkSetMacro (ActivateTimeOut, bool); itkGetMacro (ActivateTimeOut, bool); // \brief returns shortest Path as vector std::vector< itk::Index<3> > GetVectorPath(); // \brief returns Multiple shortest Paths. You can call this function, when u performed a multiple shortest path search (one start, several ends) std::vector< std::vector< itk::Index<3> > > GetMultipleVectorPaths(); // \brief returns the vector order image. It shows in which order the pixels were checked. good for debugging. Be sure to have m_StoreVectorOrder=true OutputImagePointer GetVectorOrderImage(); // \brief returns the distance image. It shows the distances from the startpoint to all other pixels. Be sure to have m_CalcAllDistances=true OutputImagePointer GetDistanceImage(); // \brief cleans up the filter void CleanUp(); itkSetObjectMacro( CostFunction, CostFunctionType ); // itkSetObjectMacro = set function that uses pointer as parameter itkGetObjectMacro( CostFunction, CostFunctionType ); protected: std::vector< IndexType > m_endPoints; // if you fill this vector, the algo will not rest until all endPoints have been reached std::vector< IndexType > m_endPointsClosed; ShortestPathNode* m_Nodes; // main list that contains all nodes NodeNumType m_Graph_NumberOfNodes; NodeNumType m_Graph_StartNode; NodeNumType m_Graph_EndNode; int m_ImageDimensions; bool m_Graph_fullNeighbors; std::vector m_Graph_DiscoveredNodeList; ShortestPathImageFilter(Self&); // intentionally not implemented void operator=(const Self&); // intentionally not implemented const static int BACKGROUND = 0; const static int FOREGROUND = 255; bool m_FullNeighborsMode; bool m_MakeOutputImage; bool m_StoreVectorOrder; // Store an Vector of Order, so you can call getVectorOrderImage after update bool m_CalcAllDistances; // Calculate all Distances, so you can call getDistanceImage after update (warning algo will take a long time) bool multipleEndPoints; bool m_ActivateTimeOut; // if true, then i search max. 30 secs. then abort CostFunctionTypePointer m_CostFunction; IndexType m_StartIndex, m_EndIndex; std::vector< itk::Index<3> > m_VectorPath; std::vector< std::vector< itk::Index<3> > > m_MultipleVectorPaths; std::vector< NodeNumType > m_VectorOrder; ShortestPathImageFilter(); // \brief Fill m_VectorPath void MakeShortestPathVector(); // \brief Create all the outputs void MakeOutputs(); // \brief Generate Data void GenerateData(); // \brief gets the estimate costs from pixel a to target. double getEstimatedCostsToTarget(const IndexType & a); typename InputImageType::Pointer m_magnitudeImage; // \brief Convert a indexnumber of a node in m_Nodes to image coordinates typename TInputImageType::IndexType NodeToCoord(NodeNumType); // \brief Convert image coordinate to a indexnumber of a node in m_Nodes unsigned int CoordToNode(IndexType); // \brief Returns the neighbors of a node std::vector GetNeighbors(NodeNumType nodeNum, bool FullNeighbors); // \brief Check if coords are in bounds of image bool CoordIsInBounds(IndexType); // \brief Initializes the graph void InitGraph(); // \brief Start ShortestPathSearch void StartShortestPathSearch(); }; } // end of namespace itk #include "itkShortestPathImageFilter.txx" #endif diff --git a/Modules/GraphAlgorithms/itkShortestPathImageFilter.txx b/Modules/GraphAlgorithms/itkShortestPathImageFilter.txx index 57b067ef24..311f5fc82a 100644 --- a/Modules/GraphAlgorithms/itkShortestPathImageFilter.txx +++ b/Modules/GraphAlgorithms/itkShortestPathImageFilter.txx @@ -1,924 +1,939 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathImageFilter_txx #define __itkShortestPathImageFilter_txx #include "time.h" #include "mitkMemoryUtilities.h" #include #include #include namespace itk { - // Constructor (initialize standard values) - template - ShortestPathImageFilter - ::ShortestPathImageFilter() : - m_FullNeighborsMode(false), - m_MakeOutputImage(true), - m_StoreVectorOrder(false), - m_CalcAllDistances(false), - m_ActivateTimeOut(false), + // Constructor (initialize standard values) + template + ShortestPathImageFilter + ::ShortestPathImageFilter() : + m_FullNeighborsMode(false), + m_MakeOutputImage(true), + m_StoreVectorOrder(false), + m_CalcAllDistances(false), + m_ActivateTimeOut(false), multipleEndPoints(false), m_Nodes(0), m_Graph_NumberOfNodes(0) - { + { m_endPoints.clear(); m_endPointsClosed.clear(); if (m_MakeOutputImage) { this->SetNumberOfRequiredOutputs(1); - this->SetNthOutput( 0, OutputImageType::New() ); + this->SetNthOutput( 0, OutputImageType::New() ); + } + } + + template + inline typename ShortestPathImageFilter::IndexType + ShortestPathImageFilter + ::NodeToCoord (NodeNumType node) + { + const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); + int dim = InputImageType::ImageDimension; + IndexType coord; + if (dim == 2) + { + coord[1] = node / size[0]; + coord[0] = node % size[0]; + if ((coord[0] >= size[0]) || (coord[1] >= size[1])) + { + coord[0] = 0; + coord[1] = 0; } - } - - template - inline typename ShortestPathImageFilter::IndexType - ShortestPathImageFilter - ::NodeToCoord (NodeNumType node) - { - const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); - int dim = InputImageType::ImageDimension; - IndexType coord; - if (dim == 2) - { - coord[1] = node / size[0]; - coord[0] = node % size[0]; - if ((coord[0] >= size[0]) || (coord[1] >= size[1])) - { - coord[0] = 0; - coord[1] = 0; - } - } - if (dim == 3) - { - coord[2] = node / (size[0]*size[1]); - coord[1] = (node % (size[0]*size[1])) / size[0]; - coord[0] = (node % (size[0]*size[1])) % size[0]; - if ((coord[0] >= size[0]) || (coord[1] >= size[1]) || (coord[2] >= size[2])) - { - coord[0] = 0; - coord[1] = 0; - coord[2] = 0; - } - } - - return coord; - } - - template - inline typename itk::NodeNumType - ShortestPathImageFilter:: - CoordToNode (IndexType coord) - { - const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); - int dim = InputImageType::ImageDimension; - NodeNumType node = 0; - if (dim == 2) - { - node = (coord[1]*size[0]) + coord[0]; - } - if (dim == 3) - { - node = (coord[2]*size[0]*size[1]) + (coord[1]*size[0]) + coord[0]; - } - if ((m_Graph_NumberOfNodes > 0) && (node >= m_Graph_NumberOfNodes)) + } + if (dim == 3) + { + coord[2] = node / (size[0]*size[1]); + coord[1] = (node % (size[0]*size[1])) / size[0]; + coord[0] = (node % (size[0]*size[1])) % size[0]; + if ((coord[0] >= size[0]) || (coord[1] >= size[1]) || (coord[2] >= size[2])) + { + coord[0] = 0; + coord[1] = 0; + coord[2] = 0; + } + } + + return coord; + } + + template + inline typename itk::NodeNumType + ShortestPathImageFilter:: + CoordToNode (IndexType coord) + { + const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); + int dim = InputImageType::ImageDimension; + NodeNumType node = 0; + if (dim == 2) + { + node = (coord[1]*size[0]) + coord[0]; + } + if (dim == 3) + { + node = (coord[2]*size[0]*size[1]) + (coord[1]*size[0]) + coord[0]; + } + if ((m_Graph_NumberOfNodes > 0) && (node >= m_Graph_NumberOfNodes)) { MITK_INFO << "WARNING! Coordinates outside image!"; MITK_INFO << "Coords = " << coord ; MITK_INFO << "ImageDim = " << dim ; MITK_INFO << "RequestedRegionSize = " << size ; - node = 0; + node = 0; + } + + return node; + } + + template + inline bool + ShortestPathImageFilter:: + CoordIsInBounds (IndexType coord) + { + const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); + int dim = InputImageType::ImageDimension; + + if (dim == 2) + { + if ((coord[0] >= 0) + && (coord[0] < size[0]) + && (coord[1] >= 0 ) + && (coord[1] < size[1] )) + { + return true; + } + } + if (dim == 3) + { + if ((coord[0] >= 0) + && (coord[0] < size[0]) + && (coord[1] >= 0 ) + && (coord[1] < size[1] ) + && (coord[2] >= 0 ) + && (coord[2] < size[2] )) + { + return true; } + } + return false; + } - return node; - } - - template - inline bool - ShortestPathImageFilter:: - CoordIsInBounds (IndexType coord) - { - const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); - int dim = InputImageType::ImageDimension; - - if (dim == 2) - { - if ((coord[0] >= 0) - && (coord[0] < size[0]) - && (coord[1] >= 0 ) - && (coord[1] < size[1] )) - { - return true; - } - } - if (dim == 3) - { - if ((coord[0] >= 0) - && (coord[0] < size[0]) - && (coord[1] >= 0 ) - && (coord[1] < size[1] ) - && (coord[2] >= 0 ) - && (coord[2] < size[2] )) - { - return true; - } - } - return false; - } - - - template - inline std::vector< ShortestPathNode* > - ShortestPathImageFilter:: - GetNeighbors (unsigned int nodeNum, bool FullNeighbors) - { - // returns a vector of nodepointers.. these nodes are the neighbors - int dim = InputImageType::ImageDimension; - IndexType Coord = NodeToCoord(nodeNum); - IndexType NeighborCoord; - std::vector nodeList; - - int neighborDistance = 1; //if i increase that, i might not hit the endnote + + template + inline std::vector< ShortestPathNode* > + ShortestPathImageFilter:: + GetNeighbors (unsigned int nodeNum, bool FullNeighbors) + { + // returns a vector of nodepointers.. these nodes are the neighbors + int dim = InputImageType::ImageDimension; + IndexType Coord = NodeToCoord(nodeNum); + IndexType NeighborCoord; + std::vector nodeList; + + int neighborDistance = 1; //if i increase that, i might not hit the endnote // maybe use itkNeighborhoodIterator here, might be faster - if ( dim == 2) - { - // N4 - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - if (FullNeighbors) - { - // N8 - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - } - } - if ( dim == 3) - { - // N6 - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - if (FullNeighbors) - { - // N26 - // Middle Slice - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - // BackSlice (Diagonal) - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - //BackSlice (Non-Diag) - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]-neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - // FrontSlice (Diagonal) - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - //FrontSlice(Non-Diag) - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]-neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]+neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]; - NeighborCoord[1] = Coord[1]+neighborDistance; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - NeighborCoord[0] = Coord[0]-neighborDistance; - NeighborCoord[1] = Coord[1]; - NeighborCoord[2] = Coord[2]+neighborDistance; - if (CoordIsInBounds(NeighborCoord)) - nodeList.push_back(&m_Nodes[CoordToNode(NeighborCoord)]); - - } - } - return nodeList; - } - - - template - void ShortestPathImageFilter:: - SetStartIndex (const typename TInputImageType::IndexType &StartIndex) - { - for (unsigned int i=0;i + void ShortestPathImageFilter:: + SetStartIndex (const typename TInputImageType::IndexType &StartIndex) + { + for (unsigned int i=0;i + inline double ShortestPathImageFilter:: + getEstimatedCostsToTarget (const typename TInputImageType::IndexType &a) + { + // Returns the minimal possible costs for a path from "a" to targetnode. itk::Vector v; - v[0] = m_EndIndex[0]-a[0]; - v[1] = m_EndIndex[1]-a[1]; - v[2] = m_EndIndex[2]-a[2]; + v[0] = m_EndIndex[0]-a[0]; + v[1] = m_EndIndex[1]-a[1]; + v[2] = m_EndIndex[2]-a[2]; return m_CostFunction->GetMinCost() * v.GetNorm(); - } - - - template - void - ShortestPathImageFilter:: - InitGraph() - { - // Clean up previous stuff - CleanUp(); - - // initalize cost function - m_CostFunction->Initialize(); - - // Calc Number of nodes - m_ImageDimensions = TInputImageType::ImageDimension; - const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); - m_Graph_NumberOfNodes = 1; - for (NodeNumType i=0; i + void + ShortestPathImageFilter:: + InitGraph() + { + // Clean up previous stuff + CleanUp(); + + // initalize cost function + m_CostFunction->Initialize(); + + // Calc Number of nodes + m_ImageDimensions = TInputImageType::ImageDimension; + const InputImageSizeType &size = this->GetInput()->GetRequestedRegion().GetSize(); + m_Graph_NumberOfNodes = 1; + for (NodeNumType i=0; i - void - ShortestPathImageFilter:: - StartShortestPathSearch() - { + template + void + ShortestPathImageFilter:: + StartShortestPathSearch() + { // Setup Timer - clock_t startAll = clock(); - clock_t stopAll = clock(); + clock_t startAll = clock(); + clock_t stopAll = clock(); // init variables - double durationAll = 0; - bool timeout = false; - bool makeNewHeapNecessary = false; + double durationAll = 0; + bool timeout = false; + bool makeNewHeapNecessary = false; NodeNumType mainNodeListIndex = 0; - DistanceType curNodeDistance = 0; - DistanceType curNodeDistAndEst = 0; + DistanceType curNodeDistance = 0; + DistanceType curNodeDistAndEst = 0; NodeNumType numberOfNodesChecked = 0; // Create Multimap (tree structure for fast searching) std::multimap myMap; std::pair< std::multimap::iterator, std::multimap::iterator> ret; std::multimap::iterator it; // At first, only startNote is discovered. myMap.insert( std::pair (m_Nodes[m_Graph_StartNode].distAndEst, &m_Nodes[m_Graph_StartNode]) ); - // While there are discovered Nodes, pick the one with lowest distance, + // While there are discovered Nodes, pick the one with lowest distance, // update its neighbors and eventually delete it from the discovered Nodes list. - while(!myMap.empty()) - { + while(!myMap.empty()) + { numberOfNodesChecked++; if ( (numberOfNodesChecked % (m_Graph_NumberOfNodes/100)) == 0) { MITK_INFO << "Checked " << ( numberOfNodesChecked / (m_Graph_NumberOfNodes/100) ) << "% List: " << myMap.size() << "\n"; } // Get element with lowest score mainNodeListIndex = myMap.begin()->second->mainListIndex; - curNodeDistAndEst = myMap.begin()->second->distAndEst; - curNodeDistance = myMap.begin()->second->distance; + curNodeDistAndEst = myMap.begin()->second->distAndEst; + curNodeDistance = myMap.begin()->second->distance; myMap.begin()->second->closed = true; // close it // Debug: //MITK_INFO << "INFO: size " << myMap.size(); /* for (it = myMap.begin(); it != myMap.end(); ++it) { MITK_INFO << "(1) " << it->first << "|" << it->second->distAndEst << "|"<second->mainListIndex; } */ - // Kicks out element with lowest score + // Kicks out element with lowest score myMap.erase( myMap.begin() ); // if wanted, store vector order - if (m_StoreVectorOrder) + if (m_StoreVectorOrder) { - m_VectorOrder.push_back(mainNodeListIndex); + m_VectorOrder.push_back(mainNodeListIndex); } - // Check neighbors - std::vector neighborNodes = GetNeighbors(mainNodeListIndex, m_Graph_fullNeighbors); - for (NodeNumType i=0; i neighborNodes = GetNeighbors(mainNodeListIndex, m_Graph_fullNeighbors); + for (NodeNumType i=0; iclosed) continue; // this nodes is already closed, go to next neighbor - IndexType coordCurNode = NodeToCoord(mainNodeListIndex); - IndexType coordNeighborNode = NodeToCoord(neighborNodes[i]->mainListIndex); + IndexType coordCurNode = NodeToCoord(mainNodeListIndex); + IndexType coordNeighborNode = NodeToCoord(neighborNodes[i]->mainListIndex); - // calculate the new Distance to the current neighbor - double newDistance = curNodeDistance - + (m_CostFunction->GetCost(coordCurNode, coordNeighborNode)); + // calculate the new Distance to the current neighbor + double newDistance = curNodeDistance + + (m_CostFunction->GetCost(coordCurNode, coordNeighborNode)); - // if it is shorter than any yet known path to this neighbor, than the current path is better. Save that! - if ((newDistance < neighborNodes[i]->distance) || (neighborNodes[i]->distance == -1) ) - { - // if that neighbornode is not in discoverednodeList yet, Push it there and update - if (neighborNodes[i]->distance == -1) - { + // if it is shorter than any yet known path to this neighbor, than the current path is better. Save that! + if ((newDistance < neighborNodes[i]->distance) || (neighborNodes[i]->distance == -1) ) + { + // if that neighbornode is not in discoverednodeList yet, Push it there and update + if (neighborNodes[i]->distance == -1) + { - neighborNodes[i]->distance = newDistance; - neighborNodes[i]->distAndEst = newDistance + getEstimatedCostsToTarget(coordNeighborNode); - neighborNodes[i]->prevNode = mainNodeListIndex; + neighborNodes[i]->distance = newDistance; + neighborNodes[i]->distAndEst = newDistance + getEstimatedCostsToTarget(coordNeighborNode); + neighborNodes[i]->prevNode = mainNodeListIndex; myMap.insert( std::pair (m_Nodes[neighborNodes[i]->mainListIndex].distAndEst, &m_Nodes[neighborNodes[i]->mainListIndex]) ); /* MITK_INFO << "Inserted: " << m_Nodes[neighborNodes[i]->mainListIndex].distAndEst << "|" << m_Nodes[neighborNodes[i]->mainListIndex].mainListIndex; MITK_INFO << "INFO: size " << myMap.size(); for (it = myMap.begin(); it != myMap.end(); ++it) { MITK_INFO << "(1) " << it->first << "|" << it->second->distAndEst << "|"<second->mainListIndex; } */ - } - // or if is already in discoverednodelist, update - else - { + } + // or if is already in discoverednodelist, update + else + { /* it = myMap.find(neighborNodes[i]->distAndEst); if (it == myMap.end() ) { MITK_INFO << "Nothing!"; // look further for (it = myMap.begin(); it != myMap.end(); ++it) { if ((*it).second->mainListIndex == lookForId) { MITK_INFO << "But it is there!!!"; MITK_INFO << "Searched for: " << lookFor << " but had: " << (*it).second->distAndEst; } } } */ // 1st : find and delete old element bool found = false; double lookFor = neighborNodes[i]->distAndEst; unsigned int lookForId = neighborNodes[i]->mainListIndex; ret = myMap.equal_range(neighborNodes[i]->distAndEst); if ((ret.first == ret.second)) { MITK_INFO << "No exact match!"; // if this happens, you are screwed /* MITK_INFO << "Was looking for: " << lookFor << " ID: " << lookForId; if (ret.first != myMap.end() ) { it = ret.first; MITK_INFO << "Found: " << it->first << " ID: " << it->second->mainListIndex; ++it; MITK_INFO << "Found: " << it->first << " ID: " << it->second->mainListIndex; --it; --it; MITK_INFO << "Found: " << it->first << " ID: " << it->second->mainListIndex; } // look if that ID is found in the map for (it = myMap.begin(); it != myMap.end(); ++it) { if ((*it).second->mainListIndex == lookForId) { MITK_INFO << "But it is there!!!"; MITK_INFO << "Searched dist: " << lookFor << " found dist: " << (*it).second->distAndEst; } } */ } else { for (it=ret.first; it!=ret.second; ++it) { if (it->second->mainListIndex == neighborNodes[i]->mainListIndex) { found = true; myMap.erase(it); /* MITK_INFO << "INFO: size " << myMap.size(); MITK_INFO << "Erase: " << it->first << "|" << it->second->mainListIndex; MITK_INFO << "INFO: size " << myMap.size(); for (it = myMap.begin(); it != myMap.end(); ++it) { MITK_INFO << "(1) " << it->first << "|" << it->second->distAndEst << "|"<second->mainListIndex; } */ break; } } } if (!found) { MITK_INFO << "Could not find it! :("; continue; } // 2nd: update and insert new element neighborNodes[i]->distance = newDistance; - neighborNodes[i]->distAndEst = newDistance + getEstimatedCostsToTarget(coordNeighborNode); - neighborNodes[i]->prevNode = mainNodeListIndex; + neighborNodes[i]->distAndEst = newDistance + getEstimatedCostsToTarget(coordNeighborNode); + neighborNodes[i]->prevNode = mainNodeListIndex; //myMap.insert( std::pair (neighborNodes[i]->distAndEst, neighborNodes[i])); myMap.insert( std::pair (m_Nodes[neighborNodes[i]->mainListIndex].distAndEst, &m_Nodes[neighborNodes[i]->mainListIndex]) ); //MITK_INFO << "Re-Inserted: " << m_Nodes[neighborNodes[i]->mainListIndex].distAndEst << "|" << m_Nodes[neighborNodes[i]->mainListIndex].mainListIndex; //MITK_INFO << "INFO: size " << myMap.size(); /*for (it = myMap.begin(); it != myMap.end(); ++it) { MITK_INFO << "(1) " << it->first << "|" << it->second->distAndEst << "|"<second->mainListIndex; }*/ - } - } - } - // finished with checking all neighbors. - - // Check Timeout, if activated - if (m_ActivateTimeOut) - { - stopAll = clock(); - durationAll = (double)(stopAll - startAll) / CLOCKS_PER_SEC; - if (durationAll >= 30) - { - MITK_INFO << "TIMEOUT!! Search took over 30 seconds"; - timeout = true ; - } - } + } + } + } + // finished with checking all neighbors. + + // Check Timeout, if activated + if (m_ActivateTimeOut) + { + stopAll = clock(); + durationAll = (double)(stopAll - startAll) / CLOCKS_PER_SEC; + if (durationAll >= 30) + { + MITK_INFO << "TIMEOUT!! Search took over 30 seconds"; + timeout = true ; + } + } // Check end criteria: // For multiple points if ( multipleEndPoints ) { // super slow, make it faster for (int i=0 ;i - void - ShortestPathImageFilter:: - MakeOutputs() - { + MITK_INFO << "Number of Nodes checked: " << m_VectorOrder.size() ; + return; + } + } + } + + template + void + ShortestPathImageFilter:: + MakeOutputs() + { MITK_INFO << "Make Output"; if (m_MakeOutputImage) { - OutputImagePointer output0 = this->GetOutput(0); - output0->SetRegions( this->GetInput()->GetLargestPossibleRegion() ); + OutputImagePointer output0 = this->GetOutput(0); + output0->SetRegions( this->GetInput()->GetLargestPossibleRegion() ); output0->Allocate(); - OutputImageIteratorType shortestPathImageIt (output0, output0->GetRequestedRegion()); + OutputImageIteratorType shortestPathImageIt (output0, output0->GetRequestedRegion()); // Create ShortestPathImage (Output 0) - for (shortestPathImageIt.GoToBegin(); !shortestPathImageIt.IsAtEnd(); ++shortestPathImageIt) - { - // First intialize with background color - shortestPathImageIt.Set( BACKGROUND ) ; - } + for (shortestPathImageIt.GoToBegin(); !shortestPathImageIt.IsAtEnd(); ++shortestPathImageIt) + { + // First intialize with background color + shortestPathImageIt.Set( BACKGROUND ) ; + } if (!multipleEndPoints) // Only one path was calculated { - for (int i=0; i< m_VectorPath.size(); i++) - { - shortestPathImageIt.SetIndex( m_VectorPath[i] ); - shortestPathImageIt.Set( FOREGROUND ) ; - } + for (int i=0; i< m_VectorPath.size(); i++) + { + shortestPathImageIt.SetIndex( m_VectorPath[i] ); + shortestPathImageIt.Set( FOREGROUND ) ; + } } else // multiple pathes has been calculated, draw all { for (int i =0; i + template typename ShortestPathImageFilter::OutputImagePointer - ShortestPathImageFilter:: - GetVectorOrderImage() - { + ShortestPathImageFilter:: + GetVectorOrderImage() + { // Create Vector Order Image // Return it - OutputImagePointer image = OutputImageType::New(); + OutputImagePointer image = OutputImageType::New(); image->SetRegions( this->GetInput()->GetLargestPossibleRegion() ); image->Allocate(); - OutputImageIteratorType vectorOrderImageIt (image, image->GetRequestedRegion()); + OutputImageIteratorType vectorOrderImageIt (image, image->GetRequestedRegion()); MITK_INFO << "GetVectorOrderImage"; for (vectorOrderImageIt.GoToBegin(); !vectorOrderImageIt.IsAtEnd(); ++vectorOrderImageIt) { // First intialize with background color vectorOrderImageIt.Value() = BACKGROUND ; } for (int i=0; i< m_VectorOrder.size(); i++) { vectorOrderImageIt.SetIndex(NodeToCoord(m_VectorOrder[i]) ); vectorOrderImageIt.Set( BACKGROUND+i) ; } - return image; - } + return image; + } - template - typename ShortestPathImageFilter::OutputImagePointer - ShortestPathImageFilter:: - GetDistanceImage() - { + template + typename ShortestPathImageFilter::OutputImagePointer + ShortestPathImageFilter:: + GetDistanceImage() + { // Create Distance Image // Return it - OutputImagePointer image = OutputImageType::New(); + OutputImagePointer image = OutputImageType::New(); image->SetRegions( this->GetInput()->GetLargestPossibleRegion() ); image->Allocate();; OutputImageIteratorType distanceImageIt (image, image->GetRequestedRegion()); // Create Distance Image (Output 1) NodeNumType myNodeNum; for (distanceImageIt.GoToBegin(); !distanceImageIt.IsAtEnd(); ++distanceImageIt) { IndexType index = distanceImageIt.GetIndex(); myNodeNum = CoordToNode(index); double newVal = m_Nodes[myNodeNum].distance; distanceImageIt.Set(newVal); } } - template - std::vector< itk::Index<3> > - ShortestPathImageFilter:: - GetVectorPath() - { - return m_VectorPath; - } + template + std::vector< itk::Index<3> > + ShortestPathImageFilter:: + GetVectorPath() + { + return m_VectorPath; + } template - std::vector< std::vector< itk::Index<3> > > - ShortestPathImageFilter:: - GetMultipleVectorPaths() - { - return m_MultipleVectorPaths; - } - - template - void - ShortestPathImageFilter:: - MakeShortestPathVector() - { + std::vector< std::vector< itk::Index<3> > > + ShortestPathImageFilter:: + GetMultipleVectorPaths() + { + return m_MultipleVectorPaths; + } + + template + void + ShortestPathImageFilter:: + MakeShortestPathVector() + { MITK_INFO << "Make ShortestPath Vec"; // single end point if ( !multipleEndPoints ) { // fill m_VectorPath with the Shortest Path m_VectorPath.clear(); - // Go backwards from endnote to startnode - NodeNumType prevNode = m_Graph_EndNode; + // Go backwards from endnote to startnode + NodeNumType prevNode = m_Graph_EndNode; while (prevNode != -1) { m_VectorPath.push_back( NodeToCoord(prevNode) ); if (prevNode == m_Graph_StartNode) break; prevNode = m_Nodes[prevNode].prevNode; } // reverse it std::reverse(m_VectorPath.begin(), m_VectorPath.end() ); } // Multiple end end points and pathes else { for (int i=0; i - void - ShortestPathImageFilter:: - CleanUp() - { + template + void + ShortestPathImageFilter:: + CleanUp() + { m_VectorPath.clear(); //TODO: if multiple Path, clear all multiple Paths - /* - for (NodeNumType i=0; i - void - ShortestPathImageFilter:: - GenerateData() - { - // Build Graph - InitGraph(); + template + void + ShortestPathImageFilter:: + GenerateData() + { + // Build Graph + InitGraph(); - // Calc Shortest Parth - StartShortestPathSearch(); + // Calc Shortest Parth + StartShortestPathSearch(); - // Fill Shortest Path - MakeShortestPathVector(); + // Fill Shortest Path + MakeShortestPathVector(); - // Make Outputs - MakeOutputs(); - } + // Make Outputs + MakeOutputs(); + } - template - void - ShortestPathImageFilter:: - PrintSelf( std::ostream& os, Indent indent ) const - { - Superclass::PrintSelf(os,indent); + template + void + ShortestPathImageFilter:: + PrintSelf( std::ostream& os, Indent indent ) const + { + Superclass::PrintSelf(os,indent); - } + } } /* end namespace itk */ #endif \ No newline at end of file diff --git a/Modules/GraphAlgorithms/itkShortestPathNode.cpp b/Modules/GraphAlgorithms/itkShortestPathNode.cpp index 975a975885..4fd836f22a 100644 --- a/Modules/GraphAlgorithms/itkShortestPathNode.cpp +++ b/Modules/GraphAlgorithms/itkShortestPathNode.cpp @@ -1,15 +1,30 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "itkShortestPathNode.h" namespace itk { -// bool ShortestPathNode::operator<(const ShortestPathNode &a) const -// { -// return (this->distance < a.distance); -// } -// bool ShortestPathNode::operator==(const ShortestPathNode &a) const -// { -// return (this->mainListIndex == a.mainListIndex); -// } +// bool ShortestPathNode::operator<(const ShortestPathNode &a) const +// { +// return (this->distance < a.distance); +// } +// bool ShortestPathNode::operator==(const ShortestPathNode &a) const +// { +// return (this->mainListIndex == a.mainListIndex); +// } } diff --git a/Modules/GraphAlgorithms/itkShortestPathNode.h b/Modules/GraphAlgorithms/itkShortestPathNode.h index c590149059..091f993c05 100644 --- a/Modules/GraphAlgorithms/itkShortestPathNode.h +++ b/Modules/GraphAlgorithms/itkShortestPathNode.h @@ -1,28 +1,43 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkShortestPathNode_h_ #define __itkShortestPathNode_h_ #include "MitkGraphAlgorithmsExports.h" namespace itk { - typedef double DistanceType; // Type to declare the costs + typedef double DistanceType; // Type to declare the costs typedef unsigned int NodeNumType; // Type for Node Numeration: unsignend int for up to 4.2 billion pixel in 32Bit system - class MitkGraphAlgorithms_EXPORT ShortestPathNode - { - public: + class MitkGraphAlgorithms_EXPORT ShortestPathNode + { + public: DistanceType distance; // minimal costs from StartPoint to this pixel - DistanceType distAndEst; // Distance+Estimated Distnace to target + DistanceType distAndEst; // Distance+Estimated Distnace to target NodeNumType prevNode; // previous node. Important to find the Shortest Path NodeNumType mainListIndex; // Indexnumber of this node in m_Nodes bool closed; // determines if this node is closes, so its optimal path to startNode is known - }; + }; - //bool operator<(const ShortestPathNode &a) const; - //bool operator==(const ShortestPathNode &a) const; + //bool operator<(const ShortestPathNode &a) const; + //bool operator==(const ShortestPathNode &a) const; } #endif diff --git a/Modules/IGT/Documentation/doxygen/IGTModule.dox b/Modules/IGT/Documentation/doxygen/IGTModule.dox index fd90af0e4e..14a175c1bd 100644 --- a/Modules/IGT/Documentation/doxygen/IGTModule.dox +++ b/Modules/IGT/Documentation/doxygen/IGTModule.dox @@ -1,13 +1,22 @@ /** \page IGTGeneralModulePage The IGT Modules \section IGTGeneralModulePageOverview Overview -These modules for image guided therapy contain functionalities for the tracking for instruments and the subsequent rendering of these instruments within MITK. +The module IGT integrates image guided therapy (IGT) functionality to MITK. The main features of MITK-IGT are: +
    +
  • handling and processing of medical imaging data which is available through MITK itself +
  • support of tracking devices +
  • a concept for processing tracking data +
-\section IGTGeneralModulePageModuleList List of IGT Modules +MITK-IGT consists of two layers for hardware control (Tracking Layer) and processing of tracking data (Navigation Layer). Additionally it offers components for rapid development of graphical user interfaces (GUIs) of navigation applications. To seperate UI functionality from the rest of the code UI classes are encapsulated in the seperate module IGT-UI. + +\section IGTGeneralModulePageModuleList List of IGT Plugins + +There are also a few ready-to-use sample applications available as MITK-Plugins: - \li \subpage org_mitk_gui_qt_igtnavigation - \li \subpage org_mitk_gui_qt_igttracking \li \subpage org_mitk_gui_qt_igtexample + \li \subpage org_mitk_gui_qt_igttracking + */ \ No newline at end of file diff --git a/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake b/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake index 5b0a329053..db98d1b08a 100644 --- a/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake +++ b/Modules/IGT/Testing/MITKIGTTrackingDeviceHardwareTesting.cmake @@ -1,17 +1,25 @@ option(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED "Enable support for testing tracking device hardware (this hardware must be connected to the system)" OFF) mark_as_advanced(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) if(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) option(MITK_NDI_AURORA_CONNECTED "Turn on if an Aurora system is connected and should be tested." OFF) option(MITK_NDI_POLARIS_CONNECTED "Turn on if a Polaris system is connected and should be tested." OFF) option(MITK_CLARON_MICRONTRACKER_CONNECTED "Turn on if a MicronTracker system is connected and should be tested." OFF) mark_as_advanced(MITK_NDI_AURORA_CONNECTED MITK_NDI_POLARIS_CONNECTED MITK_CLARON_MICRONTRACKER_CONNECTED MITK_CLARON_MICRONTRACKER_CONNECTED) endif(MITK_TRACKING_DEVICES_HARDWARE_TESTS_ENABLED) if(MITK_NDI_AURORA_CONNECTED) +if(WIN32) set(MITK_NDI_AURORA_COM_PORT "1" CACHE STRING "Serial port where the system is connected.") +else(WIN32) + set(MITK_NDI_AURORA_COM_PORT "/dev/ttyS1" CACHE STRING "Device path where the system is connected. (e.g. /dev/ttyS6 or /dev/ttyUSB1)") +endif(WIN32) endif(MITK_NDI_AURORA_CONNECTED) if(MITK_NDI_POLARIS_CONNECTED) +if(WIN32) set(MITK_NDI_POLARIS_COM_PORT "1" CACHE STRING "Serial port where the system is connected.") -endif(MITK_NDI_POLARIS_CONNECTED) \ No newline at end of file +else(WIN32) + set(MITK_NDI_POLARIS_COM_PORT "/dev/ttyS1" CACHE STRING "Device path where the system is connected. (e.g. /dev/ttyS6 or /dev/ttyUSB1)") +endif(WIN32) +endif(MITK_NDI_POLARIS_CONNECTED) diff --git a/Modules/IGT/Testing/mitkNDIAuroraHardwareTest.cpp b/Modules/IGT/Testing/mitkNDIAuroraHardwareTest.cpp index 53350eb6f5..8ada32dacd 100644 --- a/Modules/IGT/Testing/mitkNDIAuroraHardwareTest.cpp +++ b/Modules/IGT/Testing/mitkNDIAuroraHardwareTest.cpp @@ -1,88 +1,93 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNDITrackingDevice.h" #include "mitkNDIPassiveTool.h" #include "mitkTestingMacros.h" #include "mitkTrackingTypes.h" #include "mitkTrackingTool.h" #include "mitkStandardFileLocations.h" int mitkNDIAuroraHardwareTest(int argc , char* argv[]) { // always start with this! MITK_TEST_BEGIN("NDIAuroraHardware (An NDI tracking device has to be connected to this system!)"); if (argc<2) {MITK_TEST_FAILED_MSG(<<"Error: test must be called with the com port as second parameter!");} int comPort = *argv[1] - '0'; //create an aurora tracking device mitk::NDITrackingDevice::Pointer myNDITrackingDevice = mitk::NDITrackingDevice::New(); myNDITrackingDevice->SetType(mitk::NDIAurora); +#ifdef WIN32 //set port switch (comPort) { case 1: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM1); break; case 2: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM2); break; case 3: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM3); break; case 4: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM4); break; case 5: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM5); break; case 6: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM6); break; case 7: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM7); break; case 8: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM8); break; case 9: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM9); break; } +#else + MITK_INFO << std::string(argv[1]); + myNDITrackingDevice->SetDeviceName(std::string(argv[1])); +#endif //TODO: add tools //OpenConnection MITK_TEST_CONDITION( (myNDITrackingDevice->OpenConnection()), "Testing method OpenConnection()."); //StartTracking MITK_TEST_CONDITION( (myNDITrackingDevice->StartTracking()), "Testing method StartTracking()."); //TODO: test if tools are updated correctly //Stop tracking MITK_TEST_CONDITION( (myNDITrackingDevice->StopTracking()), "Testing method StopTracking()."); //CloseConnection MITK_TEST_CONDITION( (myNDITrackingDevice->CloseConnection()), "Testing behavior of method CloseConnection()."); // always end with this! MITK_TEST_END(); -} \ No newline at end of file +} diff --git a/Modules/IGT/Testing/mitkNDIPolarisHardwareTest.cpp b/Modules/IGT/Testing/mitkNDIPolarisHardwareTest.cpp index ea07012c02..c15499d36d 100644 --- a/Modules/IGT/Testing/mitkNDIPolarisHardwareTest.cpp +++ b/Modules/IGT/Testing/mitkNDIPolarisHardwareTest.cpp @@ -1,88 +1,94 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNDITrackingDevice.h" #include "mitkNDIPassiveTool.h" #include "mitkTestingMacros.h" #include "mitkTrackingTypes.h" #include "mitkTrackingTool.h" #include "mitkStandardFileLocations.h" int mitkNDIPolarisHardwareTest(int argc , char* argv[]) { // always start with this! MITK_TEST_BEGIN("NDIPolarisHardware (An NDI tracking device has to be connected to this system!)"); if (argc<2) {MITK_TEST_FAILED_MSG(<<"Error: test must be called with the com port as second parameter!");} int comPort = *argv[1] - '0'; //create a polaris tracking device mitk::NDITrackingDevice::Pointer myNDITrackingDevice = mitk::NDITrackingDevice::New(); myNDITrackingDevice->SetType(mitk::NDIPolaris); +#ifdef WIN32 //set port switch (comPort) { case 1: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM1); break; case 2: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM2); break; case 3: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM3); break; case 4: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM4); break; case 5: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM5); break; case 6: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM6); break; case 7: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM7); break; case 8: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM8); break; case 9: myNDITrackingDevice->SetPortNumber(mitk::SerialCommunication::COM9); break; } + +#else + MITK_INFO << std::string(argv[1]); + myNDITrackingDevice->SetDeviceName(std::string(argv[1])); +#endif //TODO: add tools //OpenConnection MITK_TEST_CONDITION( (myNDITrackingDevice->OpenConnection()), "Testing method OpenConnection()."); //StartTracking MITK_TEST_CONDITION( (myNDITrackingDevice->StartTracking()), "Testing method StartTracking()."); //TODO: test if tools are updated correctly //Stop tracking MITK_TEST_CONDITION( (myNDITrackingDevice->StopTracking()), "Testing method StopTracking()."); //CloseConnection MITK_TEST_CONDITION( (myNDITrackingDevice->CloseConnection()), "Testing behavior of method CloseConnection()."); // always end with this! MITK_TEST_END(); -} \ No newline at end of file +} diff --git a/Modules/ImageExtraction/Testing/files.cmake b/Modules/ImageExtraction/Testing/files.cmake index 6282bcbc93..c983818824 100644 --- a/Modules/ImageExtraction/Testing/files.cmake +++ b/Modules/ImageExtraction/Testing/files.cmake @@ -1,12 +1,13 @@ set(MODULE_IMAGE_TESTS - mitkExtractImageFilterTest.cpp + + ) set(MODULE_TESTIMAGES US4DCyl.pic.gz Pic3D.pic.gz Pic2DplusT.pic.gz BallBinary30x30x30.pic.gz Png2D-bw.png binary.stl ball.stl ) diff --git a/Modules/ImageExtraction/Testing/mitkExtractDirectedPlaneImageFilterTest.cpp b/Modules/ImageExtraction/Testing/mitkExtractDirectedPlaneImageFilterTest.cpp new file mode 100644 index 0000000000..93846b8217 --- /dev/null +++ b/Modules/ImageExtraction/Testing/mitkExtractDirectedPlaneImageFilterTest.cpp @@ -0,0 +1,297 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: 7837 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +// +//#include "mitkExtractDirectedPlaneImageFilter.h" +//#include "mitkStandardFileLocations.h" +// +//#include +//#include +//#include +//#include +//#include +// +//#include "mitkTestingMacros.h" +// +//#include +// +// +//class ExtractionTesting{ +// +//public: +// +// struct Testcase +// { +// int number; +// std::string name; +// std::string imageFilename; +// std::string referenceImageFilename; +// bool success; +// mitk::Geometry2D::Pointer (*GetPlane) (void); +// }; +// +// static void DoTesting(Testcase &testcase) +// { +// mitk::Image::Pointer image = GetImageToTest(testcase.imageFilename); +// if ( image.IsNull){ +// testcase.success = false; +// return; +// } +// +// /*mitk::Image::Pointer referenceImage = GetImageToTest(testcase.referenceImageFilename); +// if ( referenceImage.IsNull){ +// testcase.success = false; +// return; +// } +// +// mitk::Geometry2D::Pointer directedGeometry2D = testcase.GetPlane(); +// if(directedGeometry2D.IsNull){ +// testcase.success = false;*/ +// } +// +// //put testing here +// //TODO vtkIMageREslice setup +// //vtkSmartPointer colorImage = image->GetVtkImageData(); +// +// vtkSmartPointer imageMapper = vtkSmartPointer::New(); +// imageMapper->SetInput(colorImage); +// +// +// vtkSmartPointer imageActor = vtkSmartPointer::New(); +// imageActor->SetMapper(imageMapper); +// //imageActor->SetPosition(20, 20); +// +// // Setup renderers +// vtkSmartPointer renderer = vtkSmartPointer::New(); +// +// // Setup render window +// vtkSmartPointer renderWindow = vtkSmartPointer::New(); +// renderWindow->AddRenderer(renderer); +// +// // Setup render window interactor +// vtkSmartPointer renderWindowInteractor = vtkSmartPointer::New(); +// vtkSmartPointer style = vtkSmartPointer::New(); +// renderWindowInteractor->SetInteractorStyle(style); +// +// // Render and start interaction +// renderWindowInteractor->SetRenderWindow(renderWindow); +// //renderer->AddViewProp(imageActor); +// renderer->AddActor(imageActor); +// +// renderWindow->Render(); +// renderWindowInteractor->Start(); +// } +// +// +// static std::vector InitializeTestCases() +// { +// int testcounter = 0; +// std::vector tests= +// +// //#BEGIN setup TestCases +// +// { +// { +// ++testcounter, +// "TestCoronal", +// "image.nrrd", +// "coronalReference.nrrd", +// false, +// &TestCoronal +// }, +// { +// ++testcounter, +// "TestSagital", +// "image.nrrd", +// "sagitalReference.nrrd", +// false, +// &TestSagital +// }, +// { +// ++testcounter, +// "TestCoronal", +// "image.nrrd", +// "coronalReference.nrrd", +// false, +// &TestCoronal +// }, +// { +// ++testcounter, +// "Test_u_Rotation", +// "image.nrrd", +// "uRotationReference.nrrd", +// false, +// &Test_u_Rotation +// }, +// { +// ++testcounter, +// "Test_v_Rotation", +// "image.nrrd", +// "vRotationReference.nrrd", +// false, +// &Test_v_Rotation +// }, +// { +// ++testcounter, +// "TestTwoDirectionalRation", +// "image.nrrd", +// "twoDirectionalRationReference.nrrd", +// false, +// &TestTwoDirectionalRotation +// }, +// { +// ++testcounter, +// "Test4D", +// "image.nrrd", +// "twoDirectionalRationReference.nrrd", +// false, +// &Test4D +// }, +// { +// ++testcounter, +// "Test2D", +// "coronalReference.nrrd", +// "coronalReference.nrrd", +// false, +// &Test2D +// }, +// { +// ++testcounter, +// "Test2D", +// NULL, +// NULL, +// false, +// &Test1D +// } +// +// }; +// +// //#END setup TestCases +// +// return tests; +// } +// +//protected: +// +// static mitk::Image::Pointer GetImageToTest(std::string filename){ +// //retrieve referenceImage +// +//// mitk::StandardFileLocations::Pointer locator = mitk::StandardFileLocations::GetInstance(); +//// +//// const std::string filepath = locator->FindFile(filename, "Modules/MitkExt/Testing/Data"); +//// +//// if (filepath.empty()) +//// { +//// return NULL; +//// } +//// +//////TODO read imge from file +//// itk::FilenamesContainer file; +//// file.push_back( filename ); +// mitk::ItkImageFileReader::Pointer reader = mitk::ItkImageFileReader::New(); +// reader->SetFileName("C:\home\Pics\Pic3D.nrrd"); +// +// reader->Update(); +// +// mitk::Image::Pointer image = reader->GetOutput(); +// +// return image; +// } +// +// +// static mitk::Geometry2D::Pointer TestSagital() +// { +// +// return NULL; +// } +// +// static mitk::Geometry2D::Pointer TestCoronal() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer TestTransversal() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer Test_u_Rotation() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer Test_v_Rotation() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer TestTwoDirectionalRotation() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer Test4DImage() +// {return NULL; +// +// } +// +// static mitk::Geometry2D::Pointer Test2DImage() +// { +//return NULL; +// } +// +// static mitk::Geometry2D::Pointer Test1DImage() +// { +//return NULL; +// } +// +//}; +// +// +//** +// * Tests for the class "mitkExtractDirectedPlaneImageFilter". +// * +// * argc and argv are the command line parameters which were passed to +// * the ADD_TEST command in the CMakeLists.txt file. For the automatic +// * tests, argv is either empty for the simple tests or contains the filename +// * of a test image for the image tests (see CMakeLists.txt). +// */ +//int mitkExtractDirectedPlaneImageFilterTest(int /* argc */, char* /*argv*/[]) +//{ +// // always start with this! +// MITK_TEST_BEGIN("mitkExtractDirectedPlaneImageFilter") +// +// +// mitk::ExtractDirectedPlaneImageFilter::Pointer extractor = mitk::ExtractDirectedPlaneImageFilter::New(); +// MITK_TEST_CONDITION_REQUIRED(extractor.IsNotNull(),"Testing instantiation") +// +// +// std::vector allTests = ExtractionTesting::InitializeTestCases(); +// +// for( int i = 0; i < allTests.size(); i++);{ +// +// ExtractionTesting::Testcase testCase = allTest[i]; +// +// ExtractionTesting::DoTesting(testCase); +// +// MITK_TEST_CONDITION(testCase.success, "Testcase #'" << testCase.number << " " << testCase.name); +// } +// +// // always end with this! +// MITK_TEST_END() +//} \ No newline at end of file diff --git a/Modules/ImageExtraction/files.cmake b/Modules/ImageExtraction/files.cmake index 86ec6e7d9c..ebb2d57d62 100644 --- a/Modules/ImageExtraction/files.cmake +++ b/Modules/ImageExtraction/files.cmake @@ -1,11 +1,12 @@ set(CPP_FILES mitkExtractDirectedPlaneImageFilter.cpp mitkExtractDirectedPlaneImageFilterNew.cpp mitkExtractImageFilter.cpp + #mitkExtractSliceFilter.cpp ) diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp index 6fe33c2802..7a910aec58 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp @@ -1,498 +1,509 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #include "mitkExtractDirectedPlaneImageFilter.h" #include "mitkAbstractTransformGeometry.h" //#include "mitkImageMapperGL2D.h" +#include +#include +#include +#include +#include "vtkMitkThickSlicesFilter.h" + #include #include #include #include #include +#include +#include #include "pic2vtk.h" mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter() : m_WorldGeometry(NULL) { m_Reslicer = vtkImageReslice::New(); + m_TargetTimestep = 0; - m_InPlaneResampleExtentByGeometry = false; + m_InPlaneResampleExtentByGeometry = true; + m_ResliceInterpolationProperty = NULL;//VtkResliceInterpolationProperty::New(); //TODO initial with value + m_ThickSlicesMode = 0; + m_ThickSlicesNum = 1; } mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter() { - m_WorldGeometry = NULL; + if(m_ResliceInterpolationProperty!=NULL)m_ResliceInterpolationProperty->Delete(); m_Reslicer->Delete(); } void mitk::ExtractDirectedPlaneImageFilter::GenerateData() { // A world geometry must be set... if ( m_WorldGeometry == NULL ) { itkWarningMacro(<<"No world geometry has been set. Returning."); return; } Image *input = const_cast< ImageToImageFilter::InputImageType* >( this->GetInput() ); input->Update(); if ( input == NULL ) { itkWarningMacro(<<"No input set."); return; } const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); if ( ( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) { itkWarningMacro(<<"Error reading input image geometry."); return; } // Get the target timestep; if none is set, use the lowest given. unsigned int timestep = 0; if ( ! m_TargetTimestep ) { ScalarType time = m_WorldGeometry->GetTimeBounds()[0]; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) { timestep = inputTimeGeometry->MSToTimeStep( time ); } } else timestep = m_TargetTimestep; if ( inputTimeGeometry->IsValidTime( timestep ) == false ) { itkWarningMacro(<<"This is not a valid timestep: "<IsVolumeSet( timestep ) ) { itkWarningMacro(<<"No volume data existent at given timestep "<GetLargestPossibleRegion(); requestedRegion.SetIndex( 3, timestep ); requestedRegion.SetSize( 3, 1 ); requestedRegion.SetSize( 4, 1 ); input->SetRequestedRegion( &requestedRegion ); input->Update(); vtkImageData* inputData = input->GetVtkImageData( timestep ); if ( inputData == NULL ) { itkWarningMacro(<<"Could not extract vtk image data for given timestep"<GetSpacing( spacing ); // how big the area is in physical coordinates: widthInMM x heightInMM pixels mitk::ScalarType widthInMM, heightInMM; // where we want to sample Point3D origin; Vector3D right, bottom, normal; Vector3D rightInIndex, bottomInIndex; assert( input->GetTimeSlicedGeometry() == inputTimeGeometry ); // take transform of input image into account Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( timestep ); if ( inputGeometry == NULL ) { itkWarningMacro(<<"There is no Geometry3D at given timestep "<( m_WorldGeometry ) != NULL ) { const PlaneGeometry *planeGeometry = static_cast< const PlaneGeometry * >( m_WorldGeometry ); origin = planeGeometry->GetOrigin(); right = planeGeometry->GetAxisVector( 0 ); bottom = planeGeometry->GetAxisVector( 1 ); normal = planeGeometry->GetNormal(); if ( m_InPlaneResampleExtentByGeometry ) { // Resampling grid corresponds to the current world geometry. This // means that the spacing of the output 2D image depends on the // currently selected world geometry, and *not* on the image itself. extent[0] = m_WorldGeometry->GetExtent( 0 ); extent[1] = m_WorldGeometry->GetExtent( 1 ); } else { // Resampling grid corresponds to the input geometry. This means that // the spacing of the output 2D image is directly derived from the // associated input image, regardless of the currently selected world // geometry. inputGeometry->WorldToIndex( right, rightInIndex ); inputGeometry->WorldToIndex( bottom, bottomInIndex ); extent[0] = rightInIndex.GetNorm(); extent[1] = bottomInIndex.GetNorm(); } // Get the extent of the current world geometry and calculate resampling // spacing therefrom. widthInMM = m_WorldGeometry->GetExtentInMM( 0 ); heightInMM = m_WorldGeometry->GetExtentInMM( 1 ); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; right.Normalize(); bottom.Normalize(); normal.Normalize(); //origin += right * ( mmPerPixel[0] * 0.5 ); //origin += bottom * ( mmPerPixel[1] * 0.5 ); //widthInMM -= mmPerPixel[0]; //heightInMM -= mmPerPixel[1]; // Use inverse transform of the input geometry for reslicing the 3D image m_Reslicer->SetResliceTransform( inputGeometry->GetVtkTransform()->GetLinearInverse() ); // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -32768 ); // Check if a reference geometry does exist (as would usually be the case for // PlaneGeometry). // Note: this is currently not strictly required, but could facilitate // correct plane clipping. if ( m_WorldGeometry->GetReferenceGeometry() ) { // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. boundsInitialized = this->CalculateClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, bounds ); } } // Do we have an AbstractTransformGeometry? else if ( dynamic_cast< const AbstractTransformGeometry * >( m_WorldGeometry ) ) { const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); extent[0] = abstractGeometry->GetParametricExtent(0); extent[1] = abstractGeometry->GetParametricExtent(1); widthInMM = abstractGeometry->GetParametricExtentInMM(0); heightInMM = abstractGeometry->GetParametricExtentInMM(1); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; origin = abstractGeometry->GetPlane()->GetOrigin(); right = abstractGeometry->GetPlane()->GetAxisVector(0); right.Normalize(); bottom = abstractGeometry->GetPlane()->GetAxisVector(1); bottom.Normalize(); normal = abstractGeometry->GetPlane()->GetNormal(); normal.Normalize(); // Use a combination of the InputGeometry *and* the possible non-rigid // AbstractTransformGeometry for reslicing the 3D Image vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( inputGeometry->GetVtkTransform()->GetLinearInverse() ); composedResliceTransform->Concatenate( abstractGeometry->GetVtkAbstractTransform() ); m_Reslicer->SetResliceTransform( composedResliceTransform ); // Set background level to BLACK instead of translucent, to avoid // boundary artifacts (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -1023 ); composedResliceTransform->Delete(); } else { itkWarningMacro(<<"World Geometry has to be a PlaneGeometry or an AbstractTransformGeometry."); return; } // Make sure that the image to be resliced has a certain minimum size. if ( (extent[0] <= 2) && (extent[1] <= 2) ) { itkWarningMacro(<<"Image is too small to be resliced..."); return; } vtkImageChangeInformation * unitSpacingImageFilter = vtkImageChangeInformation::New() ; unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); unitSpacingImageFilter->SetInput( inputData ); m_Reslicer->SetInput( unitSpacingImageFilter->GetOutput() ); unitSpacingImageFilter->Delete(); //m_Reslicer->SetInput( inputData ); m_Reslicer->SetOutputDimensionality( 2 ); m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); Vector2D pixelsPerMM; pixelsPerMM[0] = 1.0 / mmPerPixel[0]; pixelsPerMM[1] = 1.0 / mmPerPixel[1]; //calulate the originArray and the orientations for the reslice-filter double originArray[3]; itk2vtk( origin, originArray ); m_Reslicer->SetResliceAxesOrigin( originArray ); double cosines[9]; // direction of the X-axis of the sampled result vnl2vtk( right.Get_vnl_vector(), cosines ); // direction of the Y-axis of the sampled result vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 ); // normal of the plane vnl2vtk( normal.Get_vnl_vector(), cosines + 6 ); m_Reslicer->SetResliceAxesDirectionCosines( cosines ); int xMin, xMax, yMin, yMax; if ( boundsInitialized ) { xMin = static_cast< int >( bounds[0] / mmPerPixel[0] );//+ 0.5 ); xMax = static_cast< int >( bounds[1] / mmPerPixel[0] );//+ 0.5 ); yMin = static_cast< int >( bounds[2] / mmPerPixel[1] );//+ 0.5); yMax = static_cast< int >( bounds[3] / mmPerPixel[1] );//+ 0.5 ); } else { // If no reference geometry is available, we also don't know about the // maximum plane size; so the overlap is just ignored xMin = yMin = 0; xMax = static_cast< int >( extent[0] - pixelsPerMM[0] );//+ 0.5 ); yMax = static_cast< int >( extent[1] - pixelsPerMM[1] );//+ 0.5 ); } m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], 1.0 ); // xMax and yMax are meant exclusive until now, whereas // SetOutputExtent wants an inclusive bound. Thus, we need // to subtract 1. m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 1 ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. m_Reslicer->Modified(); m_Reslicer->ReleaseDataFlagOn(); m_Reslicer->Update(); // 1. Check the result vtkImageData* reslicedImage = m_Reslicer->GetOutput(); //mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage ); if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) { itkWarningMacro(<<"Reslicer returned empty image"); return; } unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize(input->GetPixelType(), 2, dimensions ); //resultImage->Initialize( pic ); resultImage->SetSpacing( spacingVector ); //resultImage->SetPicVolume( pic ); //mitkIpPicFree(pic); /*unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize(m_Reslicer->GetOutput()); resultImage->Initialize(inputImage->GetPixelType(), 2, dimensions); resultImage->SetSpacing(spacingVector); resultImage->SetSlice(m_Reslicer->GetOutput());*/ } void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation() { - Superclass::GenerateOutputInformation(); + Superclass::GenerateOutputInformation(); } bool mitk::ExtractDirectedPlaneImageFilter ::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) { // Clip the plane with the bounding geometry. To do so, the corner points // of the bounding box are transformed by the inverse transformation // matrix, and the transformed bounding box edges derived therefrom are // clipped with the plane z=0. The resulting min/max values are taken as // bounds for the image reslicer. const BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); BoundingBox::PointType bbMin = boundingBox->GetMinimum(); BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkPoints *points = vtkPoints::New(); if(boundingGeometry->GetImageGeometry()) { points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); } else { points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); } vtkPoints *newPoints = vtkPoints::New(); vtkTransform *transform = vtkTransform::New(); transform->Identity(); transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); transform->Concatenate( boundingGeometry->GetVtkTransform() ); transform->TransformPoints( points, newPoints ); transform->Delete(); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; this->LineIntersectZero( newPoints, 0, 1, bounds ); this->LineIntersectZero( newPoints, 1, 2, bounds ); this->LineIntersectZero( newPoints, 2, 3, bounds ); this->LineIntersectZero( newPoints, 3, 0, bounds ); this->LineIntersectZero( newPoints, 0, 4, bounds ); this->LineIntersectZero( newPoints, 1, 5, bounds ); this->LineIntersectZero( newPoints, 2, 6, bounds ); this->LineIntersectZero( newPoints, 3, 7, bounds ); this->LineIntersectZero( newPoints, 4, 5, bounds ); this->LineIntersectZero( newPoints, 5, 6, bounds ); this->LineIntersectZero( newPoints, 6, 7, bounds ); this->LineIntersectZero( newPoints, 7, 4, bounds ); // clean up vtk data points->Delete(); newPoints->Delete(); if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const float *planeSpacing = planeGeometry->GetFloatSpacing(); bounds[0] *= planeSpacing[0]; bounds[1] *= planeSpacing[0]; bounds[2] *= planeSpacing[1]; bounds[3] *= planeSpacing[1]; bounds[4] *= planeSpacing[2]; bounds[5] *= planeSpacing[2]; return true; } } bool mitk::ExtractDirectedPlaneImageFilter ::LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ) + vtkFloatingPointType *bounds ) { vtkFloatingPointType point1[3]; vtkFloatingPointType point2[3]; points->GetPoint( p1, point1 ); points->GetPoint( p2, point2 ); if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) { double x, y; x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); if ( x < bounds[0] ) { bounds[0] = x; } if ( x > bounds[1] ) { bounds[1] = x; } if ( y < bounds[2] ) { bounds[2] = y; } if ( y > bounds[3] ) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; } diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h index 2d51c72c9d..8161b01819 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h @@ -1,94 +1,121 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkExtractDirectedPlaneImageFilter_h_Included #define mitkExtractDirectedPlaneImageFilter_h_Included #include "ImageExtractionExports.h" #include "mitkImageToImageFilter.h" #include "vtkImageReslice.h" +#include "mitkVtkResliceInterpolationProperty.h" + +#define setMacro(name,type) \ + virtual void Set##name (type _arg) \ + { \ + if (this->m_##name != _arg) \ + { \ + this->m_##name = _arg; \ + } \ + } + +#define getMacro(name,type) \ + virtual type Get##name () \ + { \ + return m_##name; \ + } class vtkPoints; namespace mitk { /** \brief Extracts a 2D slice of arbitrary geometry from a 3D or 4D image. \sa mitkImageMapper2D \ingroup ImageToImageFilter This class takes a 3D or 4D mitk::Image as input and tries to extract one slice from it. This slice can be arbitrary oriented in space. The 2D slice is resliced by a vtk::ResliceImage filter if not perpendicular to the input image. The world geometry of the plane to be extracted image must be given as an input to the filter in order to correctly calculate world coordinates of the extracted slice. Setting a timestep from which the plane should be extracted is optional. Output will not be set if there was a problem extracting the desired slice. Last contributor: $Author: T. Schwarz$ */ class ImageExtraction_EXPORT ExtractDirectedPlaneImageFilter : public ImageToImageFilter { public: mitkClassMacro(ExtractDirectedPlaneImageFilter, ImageToImageFilter); itkNewMacro(ExtractDirectedPlaneImageFilter); itkSetMacro( WorldGeometry, Geometry2D* ); // The Reslicer is accessible to configure the desired interpolation; // (See vtk::ImageReslice class for documentation). // Misusage is at your own risk... itkGetMacro( Reslicer, vtkImageReslice* ); // The target timestep in a 4D image from which the 2D plane is supposed // to be extracted. itkSetMacro( TargetTimestep, unsigned int ); itkGetMacro( TargetTimestep, unsigned int ); itkSetMacro( InPlaneResampleExtentByGeometry, bool ); itkGetMacro( InPlaneResampleExtentByGeometry, bool ); + setMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* ); + itkGetMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* ); + + setMacro( IsMapperMode, bool ); + getMacro( IsMapperMode, bool ); + protected: ExtractDirectedPlaneImageFilter(); // purposely hidden virtual ~ExtractDirectedPlaneImageFilter(); virtual void GenerateData(); virtual void GenerateOutputInformation(); bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); bool LineIntersectZero( vtkPoints *points, int p1, int p2, vtkFloatingPointType *bounds ); const Geometry2D* m_WorldGeometry; vtkImageReslice * m_Reslicer; - unsigned int m_TargetTimestep; - bool m_InPlaneResampleExtentByGeometry; + unsigned int m_TargetTimestep; + bool m_InPlaneResampleExtentByGeometry; + int m_ThickSlicesMode; + int m_ThickSlicesNum; + bool m_IsMapperMode; + + VtkResliceInterpolationProperty* m_ResliceInterpolationProperty; }; } // namespace mitk #endif // mitkExtractDirectedPlaneImageFilter_h_Included diff --git a/Modules/ImageStatistics/mitkvtkImageStencilRaster.h b/Modules/ImageStatistics/mitkvtkImageStencilRaster.h index 7e2c0b0bf6..bbed6dd871 100644 --- a/Modules/ImageStatistics/mitkvtkImageStencilRaster.h +++ b/Modules/ImageStatistics/mitkvtkImageStencilRaster.h @@ -1,98 +1,113 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkImageStencilData.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkImageStencilData - efficient description of an image stencil // .SECTION Description // vtkImageStencilData describes an image stencil in a manner which is // efficient both in terms of speed and storage space. The stencil extents // are stored for each x-row across the image (multiple extents per row if // necessary) and can be retrieved via the GetNextExtent() method. // .SECTION see also // vtkImageStencilSource vtkImageStencil #ifndef __vtkImageStencilRaster_h #define __vtkImageStencilRaster_h #include "vtkImageStencilData.h" #include "vtkDataObject.h" #include "ImageStatisticsExports.h" //BTX // Description: // This is a helper class for stencil creation. It is a raster with // infinite resolution in the X direction (approximately, since it uses // double precision). Lines that represent polygon edges can be drawn // into this raster, and then filled given a tolerance. class ImageStatistics_EXPORT vtkImageStencilRaster { public: // Description: // Create a raster with the specified whole y extent. vtkImageStencilRaster(const int wholeExtent[2]); // Description: // Destructor. ~vtkImageStencilRaster(); // Description: // Reset the raster to its original state, but keep the same whole // extent. Pre-allocate the specified 1D allocateExtent, which must be // within the whole extent. void PrepareForNewData(const int allocateExtent[2] = 0); // Description: // Insert a line into the raster, given the two end points. // The "inflect1" and "inflect2" should be set if you want // to add a small vertical tolerance to either endpoints. void InsertLine(const double p1[2], const double p2[2], bool inflect1, bool inflect2); // Description: // Fill the specified extent of a vtkImageStencilData with the raster, // after permuting the raster according to xj and yj. void FillStencilData(vtkImageStencilData *data, const int extent[6], int xj = 0, int yj = 1); // Description: // The tolerance for float-to-int conversions. void SetTolerance(double tol) { this->Tolerance = tol; } double GetTolerance() { return this->Tolerance; } protected: // Description: // Ensure that the raster is initialized for the specified range // of y values, which must be within the Extent. void PrepareExtent(int ymin, int ymax); // Description: // Insert an x point into the raster. If the y value is larger // than the y extent, the extent will grow automatically. void InsertPoint(int y, double x); int Extent[2]; int UsedExtent[2]; double **Raster; double Tolerance; private: vtkImageStencilRaster(const vtkImageStencilRaster&); // Not implemented. void operator=(const vtkImageStencilRaster&); // Not implemented. }; //ETX #endif diff --git a/Modules/ImageStatistics/mitkvtkLassoStencilSource.h b/Modules/ImageStatistics/mitkvtkLassoStencilSource.h index f6eb5dd66e..09f6ca6ca7 100644 --- a/Modules/ImageStatistics/mitkvtkLassoStencilSource.h +++ b/Modules/ImageStatistics/mitkvtkLassoStencilSource.h @@ -1,107 +1,122 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkLassoStencilSource.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkLassoStencilSource - Create a stencil from a contour // .SECTION Description // vtkLassoStencilSource will create an image stencil from a // set of points that define a contour. Its output can be // used with vtkImageStecil or other vtk classes that apply // a stencil to an image. // .SECTION See Also // vtkROIStencilSource vtkPolyDataToImageStencil // .SECTION Thanks // Thanks to David Gobbi for contributing this class to VTK. #ifndef __vtkLassoStencilSource_h #define __vtkLassoStencilSource_h #include "vtkImageStencilSource.h" #include "ImageStatisticsExports.h" class vtkPoints; class vtkSpline; class vtkLSSPointMap; class ImageStatistics_EXPORT vtkLassoStencilSource : public vtkImageStencilSource { public: static vtkLassoStencilSource *New(); vtkTypeMacro(vtkLassoStencilSource, vtkImageStencilSource); void PrintSelf(ostream& os, vtkIndent indent); //BTX enum { POLYGON = 0, SPLINE = 1, }; //ETX // Description: // The shape to use, default is "Polygon". The spline is a // cardinal spline. Bezier splines are not yet supported. vtkGetMacro(Shape, int); vtkSetClampMacro(Shape, int, POLYGON, SPLINE); void SetShapeToPolygon() { this->SetShape(POLYGON); }; void SetShapeToSpline() { this->SetShape(SPLINE); }; virtual const char *GetShapeAsString(); // Description: // The points that make up the lassoo. The loop does not // have to be closed, the last point will automatically be // connected to the first point by a straight line segment. virtual void SetPoints(vtkPoints *points); vtkGetObjectMacro(Points, vtkPoints); // Description: // The slice orientation. The default is 2, which is XY. // Other values are 0, which is YZ, and 1, which is XZ. vtkGetMacro(SliceOrientation, int); vtkSetClampMacro(SliceOrientation, int, 0, 2); // Description: // The points for a particular slice. This will override the // points that were set by calling SetPoints() for the slice. // To clear the setting, call SetSlicePoints(slice, NULL). virtual void SetSlicePoints(int i, vtkPoints *points); virtual vtkPoints *GetSlicePoints(int i); // Description: // Remove points from all slices. virtual void RemoveAllSlicePoints(); // Description: // Overload GetMTime() to include the timestamp on the points. unsigned long GetMTime(); protected: vtkLassoStencilSource(); ~vtkLassoStencilSource(); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); int Shape; int SliceOrientation; vtkPoints *Points; vtkSpline *SplineX; vtkSpline *SplineY; vtkLSSPointMap *PointMap; private: vtkLassoStencilSource(const vtkLassoStencilSource&); // Not implemented. void operator=(const vtkLassoStencilSource&); // Not implemented. }; #endif diff --git a/Modules/InputDevices/WiiMote/mitkKalmanFilter.cpp b/Modules/InputDevices/WiiMote/mitkKalmanFilter.cpp index 8224ba66b5..8de4cf3637 100644 --- a/Modules/InputDevices/WiiMote/mitkKalmanFilter.cpp +++ b/Modules/InputDevices/WiiMote/mitkKalmanFilter.cpp @@ -1,135 +1,150 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkKalmanFilter.h" mitk::KalmanFilter::KalmanFilter(): m_IsInitialized( false ) { m_cvKalman = cvCreateKalman( 2, 1, 0 ); m_StateVector = cvCreateMat( 2, 1, CV_32FC1); } mitk::KalmanFilter::~KalmanFilter() { } float mitk::KalmanFilter::ProcessValue( float input ) { if( m_IsInitialized ) { //// predicted value //const CvMat* y_k = cvKalmanPredict( m_cvKalman, 0 ); // measured value CvMat* z_k = cvCreateMat( 1, 1, CV_32FC1 ); float Z[] ={ (float)input }; cvInitMatHeader( z_k, 1, 1, CV_32FC1, Z ); float test123 = m_cvKalman->measurement_matrix->data.fl[0]; float test234 = m_cvKalman->measurement_matrix->data.fl[1]; // zk=H•xk+vk, cvMatMulAdd( m_cvKalman->measurement_matrix, m_StateVector /* = x_k */, z_k, z_k ); // adjust Kalman filter state cvKalmanCorrect( m_cvKalman, z_k ); // apply the transition matrix A and apply "process noise" w_k // xk=A•xk-1+wk cvMatMulAdd( m_cvKalman->transition_matrix , m_StateVector /* = x_k */ , m_cvKalman->process_noise_cov , m_StateVector /* = x_k */ ); } return 0; } void mitk::KalmanFilter::SetMeasurementNoise( float measurementNoise ) { // R - measurement noise covariance matrix // , represents position variance float r = measurementNoise; float R[]= { (float)r }; cvInitMatHeader( m_cvKalman->measurement_noise_cov, 1, 1, CV_32FC1, R ); } void mitk::KalmanFilter::SetProcessNoise( float processNoise ) { ///// SYSTEM NOISE //// // Q - process noise covariance matrix Q float q = processNoise; float Q[] = { (float)q, (float)0 }; cvInitMatHeader( m_cvKalman->process_noise_cov, 2, 1, CV_32FC1, Q ); } void mitk::KalmanFilter::ResetFilter() { // Initialize Standard Kalman Filter Variables: A,B,H,Q and R // A - (or F) relates the state at previous time step k-1 to the state at current time step k // B - control matrix, it is not used if there is no control // H - measurement matrix, // Q - process noise covariance matrix, constant or variable, // R - measurement noise covariance matrix, constant or variable // xk=A•xk-1+B•uk+wk // zk=H•xk+vk, // where: // xk (xk-1) - state of the system at the moment k (k-1) // zk - measurement of the system state at the moment k // uk - external control applied at the moment k // wk and vk are normally-distributed process and measurement noise, respectively: // p(w) ~ N(0,Q) // p(v) ~ N(0,R), // B - Optional: initialize control matrix B here /*CvMat* cvInitMatHeader( CvMat* mat , int rows , int cols , int type , void* data=NULL , int step=CV_AUTOSTEP );*/ // reset state cvSetIdentity( m_StateVector ); //// OBSERVATIONS //// // measurement matrix H float H[] = { (float)1.0, (float)12.0}; cvInitMatHeader(m_cvKalman->measurement_matrix, 1, 2, CV_32FC1, H ); float test11 = m_cvKalman->measurement_matrix->data.fl[0]; float test22 = m_cvKalman->measurement_matrix->data.fl[1]; memcpy(m_cvKalman->measurement_matrix->data.fl, H, sizeof(H)); float test1 = m_cvKalman->measurement_matrix->data.fl[0]; float test2 = m_cvKalman->measurement_matrix->data.fl[1]; //// PREDICTION MATRICES //// // P - initial prediction covariance matrix (posteriori error estimate covariance matrix) float P[] = { (float)1, (float)0 }; cvInitMatHeader(m_cvKalman->error_cov_post, 2, 1, CV_32FC1, P ); // A - relates the time states double dt = 1; double A[] = { (float)1,(float)dt, (float)0, (float)1, }; cvInitMatHeader(m_cvKalman->transition_matrix, 2, 2, CV_32FC1, A); memcpy(m_cvKalman->transition_matrix->data.fl, A, sizeof(A)); // what about kalman->state_post -> corrected state (x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) CvRNG rng = cvRNG(-1); //// init random prediction state //cvRandArr( &rng // , m_cvKalman->state_post // , CV_RAND_NORMAL // , cvRealScalar(0) // , cvRealScalar(0.1) ); m_IsInitialized = true; } \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkKalmanFilter.h b/Modules/InputDevices/WiiMote/mitkKalmanFilter.h index e0511bf89e..480d1ef5bd 100644 --- a/Modules/InputDevices/WiiMote/mitkKalmanFilter.h +++ b/Modules/InputDevices/WiiMote/mitkKalmanFilter.h @@ -1,48 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_KALMAN_FILTER_H #define MITK_KALMAN_FILTER_H // mitk #include // itk #include #include "itkObjectFactory.h" #include namespace mitk { /** * * DOES NOT YET WORK! * */ class KalmanFilter : public itk::Object { public: // only needed for smartpointer mitkClassMacro(KalmanFilter,itk::Object); itkNewMacro(Self); KalmanFilter(); virtual ~KalmanFilter(); float ProcessValue( float input ); void SetMeasurementNoise( float measurementNoise ); void SetProcessNoise( float processNoise ); void ResetFilter(); protected: private: CvKalman* m_cvKalman; CvMat* m_StateVector; // x_k bool m_IsInitialized; }; // end class } // end namespace #endif // MITK_KALMAN_FILTER_H diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.cpp index a3dc666244..d4ede0c6a3 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.cpp @@ -1,175 +1,190 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteAddOn.h" #include "mitkGlobalInteraction.h" #include "mitkInteractionConst.h" #include "mitkWiiMoteThread.h" #include "mitkWiiMoteIREvent.h" #include "mitkWiiMoteButtonEvent.h" #include "mitkWiiMoteCalibrationEvent.h" #include mitk::WiiMoteAddOn* mitk::WiiMoteAddOn::GetInstance() { static WiiMoteAddOn instance; return &instance; } mitk::WiiMoteAddOn::WiiMoteAddOn() : m_WiiMoteThread(NULL) { } mitk::WiiMoteAddOn::~WiiMoteAddOn() { this->DeactivateWiiMotes(); } void mitk::WiiMoteAddOn::ActivateWiiMotes() { if(m_WiiMoteThread == NULL) { m_WiiMoteThread = new WiiMoteThread(); m_WiiMoteThread->Run(); } } void mitk::WiiMoteAddOn::DeactivateWiiMotes() { if(m_WiiMoteThread != NULL) { m_WiiMoteThread->StopWiiMote(); //needed, otherwise the mutex wants to unlock //when the object is already destroyed Sleep(1000); m_WiiMoteThread->Delete(); m_WiiMoteThread = NULL; } } void mitk::WiiMoteAddOn::WiiMoteInput(const itk::EventObject& e) { try { // apparently the dynamic cast does not work here // reason unknown - the normal cast however works fine mitk::StateEvent* se = new mitk::StateEvent (mitk::EIDWIIMOTEINPUT, (const mitk::WiiMoteIREvent*)&e); this->ForwardEvent(se); delete se; } catch(...) { MITK_ERROR << "Incoming event is not an IR input for" << "headtracking could not be transformed\n"; } } void mitk::WiiMoteAddOn::WiiMoteButtonPressed(const itk::EventObject &e) { try { mitk::WiiMoteButtonEvent const* wiiEvent = (const mitk::WiiMoteButtonEvent*)(&e); int key = wiiEvent->GetKey(); mitk::StateEvent* se; switch(key) { case mitk::Key_Home: // view reset se = new mitk::StateEvent(mitk::EIDWIIMOTEBUTTON, wiiEvent); break; case mitk::Key_A: // calibration start/end se = new mitk::StateEvent(mitk::EV_INIT, wiiEvent); break; case mitk::Key_B: // surface interaction activation se = new mitk::StateEvent(mitk::EIDWIIMOTEBUTTONB, wiiEvent); break; } if(se != NULL) { this->ForwardEvent(se); delete se; } } catch(...) { MITK_ERROR << "Incoming event is not a button event" << "and could not be transformed\n"; } } void mitk::WiiMoteAddOn::WiiMoteButtonReleased(const itk::EventObject &e) { try { mitk::WiiMoteButtonEvent const* wiiEvent = (const mitk::WiiMoteButtonEvent*)(&e); int key = wiiEvent->GetKey(); mitk::StateEvent* se; switch(key) { case mitk::Key_B: // surface interaction deactivation se = new mitk::StateEvent(mitk::EV_DONE, wiiEvent); break; } if(se != NULL) { this->ForwardEvent(se); delete se; } } catch(...) { MITK_ERROR << "Incoming event is not a button event" << "and could not be transformed\n"; } } void mitk::WiiMoteAddOn::WiiMoteCalibrationInput(const itk::EventObject &e) { try { mitk::StateEvent* se = new mitk::StateEvent (mitk::EIDWIIMOTEINPUT, (const mitk::WiiMoteCalibrationEvent*)&e); this->ForwardEvent(se); delete se; } catch(...) { MITK_ERROR << "Incoming event is not a calibration input for headtracking" << "and could not be transformed\n"; } } void mitk::WiiMoteAddOn::SetWiiMoteSurfaceIModus(bool activated) { if(m_WiiMoteThread != NULL) { m_WiiMoteThread->SetWiiMoteSurfaceIModus(activated); } } void mitk::WiiMoteAddOn::WiiMoteSurfaceInteractionInput(const itk::EventObject& e) { try { mitk::StateEvent* se = new mitk::StateEvent (mitk::EIDWIIMOTEINPUT, (const mitk::WiiMoteAllDataEvent*)&e); this->ForwardEvent(se); delete se; } catch(...) { MITK_ERROR << "Incoming event is not an input for surface interaction" << "and could not be transformed\n"; } } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.h b/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.h index fd1daa6333..3bdbcd1e94 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteAddOn.h @@ -1,89 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEADDON_H_ #define MITK_WIIMOTEADDON_H_ // export macro #include // mitk #include "mitkVector.h" // used for Point2D #include namespace mitk { class WiiMoteThread; /** * Documentation in the interface. Some code snippets used here are from the demo
* application from gl.tter and therefore are under the same license as wiimote.cpp . * * @brief EventMapper addon for a Wiimote * @ingroup Interaction */ class mitkWiiMote_EXPORT WiiMoteAddOn : public EventMapperAddOn { public: WiiMoteAddOn(); ~WiiMoteAddOn(); // Singleton static WiiMoteAddOn* GetInstance(); /** * Starts all available Wiimotes. */ void ActivateWiiMotes(); /** * Disconnects all Wiimotes and stops the thread. */ void DeactivateWiiMotes(); /** * Creates suitable events, when the Wiimote sends IR data
* for movement and forwards it for further processing. */ void WiiMoteInput(const itk::EventObject& e); /** * Creates suitable events, when the Wiimote sends button events
* to trigger an action and forwards it for further processing. */ void WiiMoteButtonPressed(const itk::EventObject& e); /** * Creates suitable events, when the Wiimote sends button events
* to trigger an action and forwards it for further processing. */ void WiiMoteButtonReleased(const itk::EventObject& e); /** * Creates suitable events, when the Wiimote sends IR data
* to configure the sensitivity and forwards it for further processing. */ void WiiMoteCalibrationInput(const itk::EventObject& e); /** * @see mitk::WiiMoteThread::SetWiiMoteSurfaceIModus(bool activated) */ void SetWiiMoteSurfaceIModus(bool activated); /** * Creates suitable events, regardless what type of data the
* Wiimote sends for a surface interaction. Then forwards the
* transformed data for further processing. * */ void WiiMoteSurfaceInteractionInput(const itk::EventObject& e); protected: private: WiiMoteThread* m_WiiMoteThread; }; // end class WiiMoteAddOn } // end namespace mitk #endif // MITK_WIIMOTEADDON_H_ diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.cpp index 59d37b4c4b..a552fbef19 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.cpp @@ -1,221 +1,236 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include mitk::WiiMoteAllDataEvent::WiiMoteAllDataEvent (int eventType , float pitchSpeed , float rollSpeed , float yawSpeed , float orientationX , float orientationY , float orientationZ , float roll , float pitch , float xAcceleration , float yAcceleration , float zAcceleration , int surfaceInteractionMode) : Event(NULL, eventType, mitk::BS_NoButton, mitk::BS_NoButton, Key_none) , m_IRDotRawX(0) , m_IRDotRawY(0) , m_Button(0) , m_PitchSpeed(pitchSpeed) , m_RollSpeed(rollSpeed) , m_YawSpeed(yawSpeed) , m_OrientationX(orientationX) , m_OrientationY(orientationY) , m_OrientationZ(orientationZ) , m_Roll(roll) , m_Pitch(pitch) , m_XAcceleration(xAcceleration) , m_YAcceleration(yAcceleration) , m_ZAcceleration(zAcceleration) , m_SurfaceInteractionMode(surfaceInteractionMode) { } mitk::WiiMoteAllDataEvent::~WiiMoteAllDataEvent() { } void mitk::WiiMoteAllDataEvent::SetIRDotRawX(float xCoordinate) { this->m_IRDotRawX = xCoordinate; } float mitk::WiiMoteAllDataEvent::GetIRDotRawY() const { return this-> m_IRDotRawX; } void mitk::WiiMoteAllDataEvent::SetIRDotRawY(float yCoordinate) { this->m_IRDotRawY = yCoordinate; } float mitk::WiiMoteAllDataEvent::GetIRDotRawX() const { return this->m_IRDotRawY; } void mitk::WiiMoteAllDataEvent::SetButton(int button) { this->m_Button = button; } int mitk::WiiMoteAllDataEvent::GetButton() const { return this->m_Button; } void mitk::WiiMoteAllDataEvent::SetPitchSpeed(float pitchSpeed) { this->m_PitchSpeed = pitchSpeed; } float mitk::WiiMoteAllDataEvent::GetPitchSpeed() const { return this->m_PitchSpeed; } void mitk::WiiMoteAllDataEvent::SetRollSpeed(float rollSpeed) { this->m_RollSpeed = rollSpeed; } float mitk::WiiMoteAllDataEvent::GetRollSpeed() const { return this->m_RollSpeed; } void mitk::WiiMoteAllDataEvent::SetYawSpeed(float yawSpeed) { this->m_YawSpeed = yawSpeed; } float mitk::WiiMoteAllDataEvent::GetYawSpeed() const { return this->m_YawSpeed; } void mitk::WiiMoteAllDataEvent::SetOrientationX(float orientationX) { this->m_OrientationX = orientationX; } float mitk::WiiMoteAllDataEvent::GetOrientationX() const { return this->m_OrientationX; } void mitk::WiiMoteAllDataEvent::SetOrientationY(float orientationY) { this->m_OrientationY = orientationY; } float mitk::WiiMoteAllDataEvent::GetOrientationY() const { return this->m_OrientationY; } void mitk::WiiMoteAllDataEvent::SetOrientationZ(float orientationZ) { this->m_OrientationZ = orientationZ; } float mitk::WiiMoteAllDataEvent::GetOrientationZ() const { return this->m_OrientationZ; } void mitk::WiiMoteAllDataEvent::SetRoll(float roll) { this->m_Roll = roll; } float mitk::WiiMoteAllDataEvent::GetRoll() const { return this->m_Roll; } void mitk::WiiMoteAllDataEvent::SetPitch(float pitch) { this->m_Pitch = pitch; } float mitk::WiiMoteAllDataEvent::GetPitch() const { return this->m_Pitch; } void mitk::WiiMoteAllDataEvent::SetXAcceleration(float xAcceleration) { this->m_XAcceleration = xAcceleration; } float mitk::WiiMoteAllDataEvent::GetXAcceleration() const { return this->m_XAcceleration; } void mitk::WiiMoteAllDataEvent::SetYAcceleration(float yAcceleration) { this->m_YAcceleration = yAcceleration; } float mitk::WiiMoteAllDataEvent::GetYAcceleration() const { return this->m_YAcceleration; } void mitk::WiiMoteAllDataEvent::SetZAcceleration(float zAcceleration) { this->m_ZAcceleration; } float mitk::WiiMoteAllDataEvent::GetZAcceleration() const { return this->m_ZAcceleration; } void mitk::WiiMoteAllDataEvent::SetSurfaceInteractionMode(int mode) { this->m_SurfaceInteractionMode = mode; } int mitk::WiiMoteAllDataEvent::GetSurfaceInteractionMode() const { return this->m_SurfaceInteractionMode; } // ------------------------- itk::EventObject Implementation ----------------------- const char* mitk::WiiMoteAllDataEvent::GetEventName() const { return "WiiMoteAllDataEvent"; } bool mitk::WiiMoteAllDataEvent::CheckEvent(const itk::EventObject *e) const { return dynamic_cast(e); } itk::EventObject* mitk::WiiMoteAllDataEvent::MakeObject() const { return new Self (this->GetType() ,this->GetPitchSpeed() ,this->GetRollSpeed() ,this->GetYawSpeed() ,this->GetOrientationX() ,this->GetOrientationY() ,this->GetOrientationZ() ,this->GetRoll() ,this->GetPitch() ,this->GetXAcceleration() ,this->GetYAcceleration() ,this->GetZAcceleration() ,this->GetSurfaceInteractionMode() ); } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.h b/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.h index f081bcb5e6..bee8ac22ad 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteAllDataEvent.h @@ -1,147 +1,162 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTE_ALLDATAEVENT_H #define MITK_WIIMOTE_ALLDATAEVENT_H // mitk #include // export macro #include namespace mitk { /** * This event type is used to store all data available from the
* Wiimote driver. This includes IR, button, orientation, and acceleration input. */ class mitkWiiMote_EXPORT WiiMoteAllDataEvent: public Event, itk::EventObject { public: // unnecessary number of parameter because // the method MakeObject() from itk::EventObject // defines the data, that is able to travel from // thread to thread; i.e. everything, which is not // in the constructor will not be usable in the // other thread WiiMoteAllDataEvent ( int eventType , float pitchSpeed , float rollSpeed , float yawSpeed , float orientationX , float orientationY , float orientationZ , float roll , float pitch , float xAcceleration , float yAcceleration , float zAcceleration , int surfaceInteractionMode); ~WiiMoteAllDataEvent(); void SetIRDotRawX(float xCoordinate); float GetIRDotRawX() const; void SetIRDotRawY(float yCoordinate); float GetIRDotRawY() const; void SetButton(int button); int GetButton() const; void SetPitchSpeed(float pitchSpeed); float GetPitchSpeed() const; void SetRollSpeed(float rollSpeed); float GetRollSpeed() const; void SetYawSpeed(float yawSpeed); float GetYawSpeed() const; void SetOrientationX(float orientationX); float GetOrientationX() const; void SetOrientationY(float orientationY); float GetOrientationY() const; void SetOrientationZ(float orientationZ); float GetOrientationZ() const; void SetRoll(float roll); float GetRoll() const; void SetPitch(float pitch); float GetPitch() const; void SetXAcceleration(float xAcceleration); float GetXAcceleration() const; void SetYAcceleration(float yAcceleration); float GetYAcceleration() const; void SetZAcceleration(float zAcceleration); float GetZAcceleration() const; void SetSurfaceInteractionMode(int mode); int GetSurfaceInteractionMode() const; //itk::EventObject implementation typedef WiiMoteAllDataEvent Self; typedef itk::EventObject Superclass; const char * GetEventName() const; bool CheckEvent(const ::itk::EventObject* e) const; ::itk::EventObject* MakeObject() const; protected: private: // IR data // there are in fact 4 registerable dots // but at the moment data from one is sufficient float m_IRDotRawX; float m_IRDotRawY; // button data int m_Button; // the name of the button // acceleration data // angle speed from motion plus // the unit is degree per second float m_PitchSpeed; float m_RollSpeed; float m_YawSpeed; // linear acceleration from wiimote // the unit is g // range: -3..0..+3 float m_XAcceleration; float m_YAcceleration; float m_ZAcceleration; // orientation data // the unit is g // range: -1..0..1 float m_OrientationX; float m_OrientationY; float m_OrientationZ; // range: -180..0..180 degree float m_Pitch; // range: -90..0..90 degree float m_Roll; // time between the last orientation estimate update // if update age is too high the acceleration // values are likely to be out of date unsigned m_UpdateAge; // surface interaction mode int m_SurfaceInteractionMode; }; // end class } // end namespace #endif // MITK_WIIMOTE_ALLDATAEVENT_H diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.cpp index df6ef172c2..7940cc9dfe 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.cpp @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteButtonEvent.h" mitk::WiiMoteButtonEvent::WiiMoteButtonEvent(int type, int button, int buttonState, int key) : Event(NULL, type, button, buttonState, key) { } mitk::WiiMoteButtonEvent::~WiiMoteButtonEvent() { } const char* mitk::WiiMoteButtonEvent::GetEventName() const { return "WiiMoteButtonEvent"; } bool mitk::WiiMoteButtonEvent::CheckEvent(const itk::EventObject *e) const { return dynamic_cast(e); } itk::EventObject* mitk::WiiMoteButtonEvent::MakeObject() const { return new Self(m_Type, m_Button, m_ButtonState, m_Key); } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.h b/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.h index 03721413b2..03d355bb5f 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteButtonEvent.h @@ -1,43 +1,58 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEBUTTONEVENT_H #define MITK_WIIMOTEBUTTONEVENT_H #include "mitkEvent.h" #include "mitkVector.h" #include "mitkInteractionConst.h" #include "mitkWiiMoteExports.h" namespace mitk { /** * This event type is used for button events triggered by the
* the Wiimote driver. */ class mitkWiiMote_EXPORT WiiMoteButtonEvent : public Event, itk::EventObject { public: typedef WiiMoteButtonEvent Self; typedef itk::EventObject Superclass; /** * Initializes a Wiimote Event, that stores additional information.
* * @see mitk::Event::Event(mitk::BaseRenderer* sender, int type, int button, int buttonState, int key); */ WiiMoteButtonEvent(int type, int button, int buttonState, int key); ~WiiMoteButtonEvent(); //itk::EventObject implementation const char * GetEventName() const; bool CheckEvent(const ::itk::EventObject* e) const; ::itk::EventObject* MakeObject() const; protected: private: }; // end class } // end namespace mitk #endif // MITK_WIIMOTEBUTTONEVENT_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.cpp index 36b74c97d9..239692af76 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.cpp @@ -1,37 +1,52 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteCalibrationEvent.h" mitk::WiiMoteCalibrationEvent::WiiMoteCalibrationEvent(double rawX, double rawY) : Event(NULL, mitk::Type_WiiMoteInput, mitk::BS_NoButton, mitk::BS_NoButton, Key_none) { m_RawX = rawX; m_RawY = rawY; } mitk::WiiMoteCalibrationEvent::~WiiMoteCalibrationEvent() { } double mitk::WiiMoteCalibrationEvent::GetXCoordinate() const { return m_RawX; } double mitk::WiiMoteCalibrationEvent::GetYCoordinate() const { return m_RawY; } const char* mitk::WiiMoteCalibrationEvent::GetEventName() const { return "WiiMoteCalibrationEvent"; } bool mitk::WiiMoteCalibrationEvent::CheckEvent(const itk::EventObject *e) const { return dynamic_cast(e); } itk::EventObject* mitk::WiiMoteCalibrationEvent::MakeObject() const { return new Self(m_RawX, m_RawY); } \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.h b/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.h index 65702b12ae..e4b15953ee 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteCalibrationEvent.h @@ -1,51 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTECALIBRATIONEVENT_H #define MITK_WIIMOTECALIBRATIONEVENT_H #include "mitkWiiMoteExports.h" #include "mitkEvent.h" #include "mitkVector.h" #include "mitkInteractionConst.h" namespace mitk { class mitkWiiMote_EXPORT WiiMoteCalibrationEvent : public Event, itk::EventObject { public: typedef WiiMoteCalibrationEvent Self; typedef itk::EventObject Superclass; /** * Initializes a Wiimote Event, that stores additional information.
* Such as a the raw x and y coordinates of the IR input.
* * @param rawX * x coordinate of the IR sensor input * @param rawY * y coordinate of the IR sensor input */ WiiMoteCalibrationEvent(double rawX, double rawY); ~WiiMoteCalibrationEvent(); double GetXCoordinate() const; double GetYCoordinate() const; //itk::EventObject implementation const char * GetEventName() const; bool CheckEvent(const ::itk::EventObject* e) const; ::itk::EventObject* MakeObject() const; protected: private: double m_RawX; double m_RawY; }; } #endif // MITK_WIIMOTECALIBRATIONEVENT_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.cpp index e143736e0a..b3853c91f0 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.cpp @@ -1,48 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteIREvent.h" mitk::WiiMoteIREvent::WiiMoteIREvent( mitk::Vector2D inputData , double recordTime , int sliceNavigationValue ) : Event(NULL, mitk::Type_WiiMoteInput, mitk::BS_NoButton, mitk::BS_NoButton, Key_none) { this->m_MovementVector = inputData; this->m_RecordTime = recordTime; this->m_SliceNavigationValue = sliceNavigationValue; } mitk::WiiMoteIREvent::~WiiMoteIREvent() { } mitk::Vector2D mitk::WiiMoteIREvent::GetMovementVector() const { return m_MovementVector; } double mitk::WiiMoteIREvent::GetRecordTime() const { return m_RecordTime; } int mitk::WiiMoteIREvent::GetSliceNavigationValue() const { return m_SliceNavigationValue; } const char* mitk::WiiMoteIREvent::GetEventName() const { return "WiiMoteIREvent"; } bool mitk::WiiMoteIREvent::CheckEvent(const itk::EventObject *e) const { return dynamic_cast(e); } itk::EventObject* mitk::WiiMoteIREvent::MakeObject() const { return new Self( this->GetMovementVector() , this->GetRecordTime() , this->GetSliceNavigationValue() ); } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.h b/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.h index 059c044991..a4270b58fa 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteIREvent.h @@ -1,60 +1,75 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEIREVENT_H #define MITK_WIIMOTEIREVENT_H #include "mitkEvent.h" #include "mitkVector.h" #include "mitkInteractionConst.h" #include "mitkWiiMoteExports.h" namespace mitk { /** * This event type is used for IR events triggered by the
* the Wiimote driver. */ class mitkWiiMote_EXPORT WiiMoteIREvent : public Event, itk::EventObject { public: typedef WiiMoteIREvent Self; typedef itk::EventObject Superclass; /** * Initializes a Wiimote Event, that stores additional information.
* Such as a vector and the time of the recording
* * @param inputData * the movement of the IR sensor computed in a vector * @param recordTime * the time at which the data was recorded */ WiiMoteIREvent( mitk::Vector2D inputData , double recordTime , int sliceNavigationValue); ~WiiMoteIREvent(); /** * Returns the current movement vector with the coordinates
* in the following order: x, y, z */ mitk::Vector2D GetMovementVector() const; double GetRecordTime() const; int GetSliceNavigationValue() const; //itk::EventObject implementation const char * GetEventName() const; bool CheckEvent(const ::itk::EventObject* e) const; ::itk::EventObject* MakeObject() const; private: mitk::Vector2D m_MovementVector; double m_RecordTime; int m_SliceNavigationValue; }; // end class } // end namespace mitk #endif // MITK_WIIMOTEIREVENT_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.cpp index c6b90d7773..cd7701dc29 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.cpp @@ -1,761 +1,776 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include // mitk #include #include #include #include #include #include #include #include #include // vtk #include #include #include #include #include // vnl #include #include #define _USE_MATH_DEFINES // otherwise, constants will not work #include const double DELTATIME = 0.01; mitk::WiiMoteInteractor::WiiMoteInteractor(const char* type, DataNode* dataNode) : Interactor(type, dataNode) , m_OrientationX(0) , m_OrientationY(0) , m_OrientationZ(0) , m_xVelocity (0) , m_yVelocity (0) , m_zVelocity (0) , m_xAngle (0) , m_yAngle (0) , m_zAngle (0) , m_xValue (0) , m_yValue (0) , m_zValue (0) , m_InRotation(false) , m_TranslationMode(1) , m_OriginalGeometry(NULL) , m_SurfaceInteractionMode(1) { // save original geometry mitk::Geometry3D* temp = this->TransformCurrentDataInGeometry3D(); try { m_OriginalGeometry = dynamic_cast(temp->Clone().GetPointer()); } catch(...) { MITK_WARN << "Original geometry could not be stored!"; } // connect actions to methods CONNECT_ACTION(mitk::AcONWIIMOTEINPUT,OnWiiMoteInput); CONNECT_ACTION(mitk::AcONWIIMOTEBUTTONRELEASED,OnWiiMoteReleaseButton); CONNECT_ACTION(mitk::AcRESETVIEW,OnWiiMoteResetButton); } mitk::WiiMoteInteractor::~WiiMoteInteractor() { } bool mitk::WiiMoteInteractor::OnWiiMoteResetButton(Action* action, const mitk::StateEvent* stateEvent) { // resets the geometry, so that the // object will be returned to its // initial state try { mitk::Surface* surface = dynamic_cast(m_DataNode->GetData()); mitk::Geometry3D::Pointer temp = dynamic_cast(m_OriginalGeometry->Clone().GetPointer()); surface->SetGeometry(temp); if(surface == NULL) { MITK_WARN << "Original geometry could not be used for reset!"; } m_DataNode->SetData(surface); m_DataNode->Modified(); } catch(...) { MITK_ERROR << "Original geometry could not be retrieved"; } //reset the camera, so that the objects shown in the scene can be seen. const mitk::BaseRenderer* br = mitk::GlobalInteraction::GetInstance()->GetFocus(); const mitk::VtkPropRenderer* glRenderer = dynamic_cast(br); if (glRenderer) { vtkRenderer* vtkRenderer = glRenderer->GetVtkRenderer(); mitk::DataStorage* ds = br->GetDataStorage(); if (ds == NULL) return false; mitk::BoundingBox::Pointer bb = ds->ComputeBoundingBox(); mitk::Point3D middle = bb->GetCenter(); vtkRenderer->GetActiveCamera()->SetFocalPoint(middle[0],middle[1],middle[2]); vtkRenderer->ResetCamera(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } bool mitk::WiiMoteInteractor::OnWiiMoteInput(Action* action, const mitk::StateEvent* stateEvent) { const mitk::WiiMoteAllDataEvent* wiiMoteEvent; try { wiiMoteEvent = dynamic_cast(stateEvent->GetEvent()); } catch(...) { MITK_ERROR << "Event is not wiimote event and could not be transformed\n"; } m_SurfaceInteractionMode = wiiMoteEvent->GetSurfaceInteractionMode(); //this->FixedRotationAndTranslation(wiiMoteEvent); // -------------------- values for translation -------------------- float xAccel = wiiMoteEvent->GetXAcceleration(); float yAccel = wiiMoteEvent->GetYAcceleration(); float zAccel = wiiMoteEvent->GetZAcceleration(); float pitch = wiiMoteEvent->GetPitch(); float roll = wiiMoteEvent->GetRoll(); m_OrientationX = wiiMoteEvent->GetOrientationX(); m_OrientationY = wiiMoteEvent->GetOrientationY(); m_OrientationZ = wiiMoteEvent->GetOrientationZ(); // substracts the proportionate force // applied by gravity depending on the // orientation float sinP = sin(pitch/180.0 * M_PI); float cosP = cos(pitch/180.0 * M_PI); float sinR = sin(roll/180.0 * M_PI); float cosR = cos(roll/180.0 * M_PI); // x acceleration if(m_OrientationZ >= 0) { m_xValue = xAccel - sinR * cosP; } else { m_xValue = xAccel + sinR * cosP; } //// against drift //if(std::abs(xAccel) < 0.2) //{ // m_xValue = 0; //} // y acceleration m_yValue = yAccel + sinP; //// against drift //if(std::abs(yAccel) < 0.2) //{ // m_yValue = 0; //} // z acceleration m_zValue = zAccel - cosP * cosR; //// against drift //if(std::abs(zAccel) < 0.3) //{ // m_zValue = 0; //} m_xVelocity += m_xValue; m_yVelocity += m_yValue; m_zVelocity -= m_zValue; // -------------------- values for rotation -------------------- ScalarType pitchSpeed = wiiMoteEvent->GetPitchSpeed(); ScalarType rollSpeed = wiiMoteEvent->GetRollSpeed(); ScalarType yawSpeed = wiiMoteEvent->GetYawSpeed(); // x angle if(std::abs(pitchSpeed) > 50 && std::abs(pitchSpeed) < 1000) { if(m_SurfaceInteractionMode == 1) { m_xAngle = (pitchSpeed * DELTATIME); } else { m_xAngle = (-pitchSpeed * DELTATIME); } } else { m_xAngle = 0; } // y angle if(std::abs(rollSpeed) > 50 && std::abs(rollSpeed) < 1000) { m_yAngle = (rollSpeed * DELTATIME); } else { m_yAngle = 0; } // z angle if(std::abs(yawSpeed) > 50 && std::abs(yawSpeed) < 1000) { if(m_SurfaceInteractionMode == 1) { m_zAngle = (yawSpeed * DELTATIME); } else { m_zAngle = (-yawSpeed * DELTATIME); } } else { m_zAngle = 0; } // -------------------- rotation and translation -------------------- bool result = false; result = this->DynamicRotationAndTranslation(this->TransformCurrentDataInGeometry3D()); return result; } bool mitk::WiiMoteInteractor::OnWiiMoteReleaseButton(Action* action, const mitk::StateEvent* stateEvent) { m_xVelocity = 0; m_yVelocity = 0; m_zVelocity = 0; m_xValue = 0; m_yValue = 0; m_zValue = 0; m_xAngle = 0; m_yAngle = 0; m_zAngle = 0; // only for fixed translation m_InRotation = false; m_TranslationMode = 1; return true; } mitk::Geometry3D* mitk::WiiMoteInteractor::TransformCurrentDataInGeometry3D() { //checking corresponding Data; has to be a surface or a subclass mitk::Surface* surface = dynamic_cast(m_DataNode->GetData()); if ( surface == NULL ) { MITK_WARN<<"Wiimote Interactor got wrong type of data! Aborting interaction!\n"; return NULL; } Geometry3D* geometry = surface->GetUpdatedTimeSlicedGeometry()->GetGeometry3D( m_TimeStep ); return geometry; } vnl_matrix_fixed mitk::WiiMoteInteractor::ComputeCurrentCameraPosition( vtkCamera* vtkCamera ) { vnl_matrix_fixed cameraMat; //first we need the position of the camera mitk::Vector3D camPosition; double camPositionTemp[3]; vtkCamera->GetPosition(camPositionTemp); camPosition[0] = camPositionTemp[0]; camPosition[1] = camPositionTemp[1]; camPosition[2] = camPositionTemp[2]; //then the upvector of the camera mitk::Vector3D upCamVector; double upCamTemp[3]; vtkCamera->GetViewUp(upCamTemp); upCamVector[0] = upCamTemp[0]; upCamVector[1] = upCamTemp[1]; upCamVector[2] = upCamTemp[2]; upCamVector.Normalize(); //then the vector to which the camera is heading at (focalpoint) mitk::Vector3D focalPoint; double focalPointTemp[3]; vtkCamera->GetFocalPoint(focalPointTemp); focalPoint[0] = focalPointTemp[0]; focalPoint[1] = focalPointTemp[1]; focalPoint[2] = focalPointTemp[2]; mitk::Vector3D focalVector; focalVector = focalPoint - camPosition; focalVector.Normalize(); //orthogonal vector to focalVector and upCamVector mitk::Vector3D crossVector; crossVector = CrossProduct(upCamVector, focalVector); crossVector.Normalize(); cameraMat.put(0,0,crossVector[0]); cameraMat.put(1,0,crossVector[1]); cameraMat.put(2,0,crossVector[2]); cameraMat.put(3,0,0); cameraMat.put(0,1,focalVector[0]); cameraMat.put(1,1,focalVector[1]); cameraMat.put(2,1,focalVector[2]); cameraMat.put(3,1,0); cameraMat.put(0,2,upCamVector[0]); cameraMat.put(1,2,upCamVector[1]); cameraMat.put(2,2,upCamVector[2]); cameraMat.put(3,2,0); cameraMat.put(0,3,camPosition[0]); cameraMat.put(1,3,camPosition[1]); cameraMat.put(2,3,camPosition[2]); cameraMat.put(3,3,1); return cameraMat; } bool mitk::WiiMoteInteractor::DynamicRotationAndTranslation(Geometry3D* geometry) { // computation of the delta transformation if(m_SurfaceInteractionMode == 1) { // necessary because the wiimote has // a different orientation when loaded // as an object file ScalarType temp = m_yAngle; m_yAngle = m_zAngle; m_zAngle = temp; } //vnl_quaternion Rx(m_OrientationX // ,m_OrientationY // ,m_OrientationZ // , m_xAngle); //vnl_quaternion Ry(Rx.axis()[0] // , Rx.axis()[1] // , Rx.axis()[2] // , m_yAngle); //vnl_quaternion Rz(Ry.axis()[0] // , Ry.axis()[1] // , Ry.axis()[2] // , m_zAngle); vnl_quaternion q( vtkMath::RadiansFromDegrees( m_xAngle ), vtkMath::RadiansFromDegrees( m_yAngle ), vtkMath::RadiansFromDegrees( m_zAngle ) ); //q = Rz * Ry * Rx; //q.normalize(); vnl_matrix_fixed deltaTransformMat = q.rotation_matrix_transpose_4(); // fill translation column deltaTransformMat(0,3) = m_xVelocity; deltaTransformMat(1,3) = m_yVelocity; deltaTransformMat(2,3) = m_zVelocity; // invert matrix to apply // correct order for the transformation deltaTransformMat = vnl_inverse(deltaTransformMat); vtkMatrix4x4* deltaTransform = vtkMatrix4x4::New(); // copy into matrix for(size_t i=0; i<4; ++i) for(size_t j=0; j<4; ++j) deltaTransform->SetElement(i,j, deltaTransformMat(i,j)); vtkMatrix4x4* objectTransform = vtkMatrix4x4::New(); if(m_SurfaceInteractionMode == 2) { // additional computation for transformation // relative to the camera view // get renderer const RenderingManager::RenderWindowVector& renderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); for ( RenderingManager::RenderWindowVector::const_iterator iter = renderWindows.begin(); iter != renderWindows.end(); ++iter ) { if ( mitk::BaseRenderer::GetInstance((*iter))->GetMapperID() == BaseRenderer::Standard3D ) { m_BaseRenderer = mitk::BaseRenderer::GetInstance((*iter)); } } vtkCamera* camera = m_BaseRenderer->GetVtkRenderer()->GetActiveCamera(); //vtkMatrix4x4* cameraMat = vtkMatrix4x4::New(); vnl_matrix_fixed cameraMat; vnl_matrix_fixed objectMat; // copy object matrix for(size_t i=0; i<4; ++i) for(size_t j=0; j<4; ++j) objectMat.put(i,j, geometry->GetVtkTransform()->GetMatrix()->GetElement(i,j)); cameraMat = this->ComputeCurrentCameraPosition(camera); vnl_matrix_fixed newObjectMat; vnl_matrix_fixed objectToCameraMat; objectToCameraMat = vnl_inverse(cameraMat) * objectMat; newObjectMat = vnl_inverse(objectToCameraMat) * deltaTransformMat * objectToCameraMat * vnl_inverse(objectMat); newObjectMat = vnl_inverse(newObjectMat); newObjectMat.put(0,3,objectMat(0,3)+deltaTransformMat(0,3)); newObjectMat.put(1,3,objectMat(1,3)+deltaTransformMat(1,3)); newObjectMat.put(2,3,objectMat(2,3)+deltaTransformMat(2,3)); // copy result for(size_t i=0; i<4; ++i) for(size_t j=0; j<4; ++j) objectTransform->SetElement(i,j, newObjectMat(i,j)); } //copy m_vtkMatrix to m_VtkIndexToWorldTransform geometry->TransferItkToVtkTransform(); vtkTransform* vtkTransform = vtkTransform::New(); if(m_SurfaceInteractionMode == 1) { //m_VtkIndexToWorldTransform as vtkLinearTransform* vtkTransform->SetMatrix( geometry->GetVtkTransform()->GetMatrix() ); vtkTransform->Concatenate( deltaTransform ); geometry->SetIndexToWorldTransformByVtkMatrix( vtkTransform->GetMatrix() ); } else { geometry->SetIndexToWorldTransformByVtkMatrix( objectTransform ); } geometry->Modified(); m_DataNode->Modified(); vtkTransform->Delete(); objectTransform->Delete(); deltaTransform->Delete(); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } bool mitk::WiiMoteInteractor::FixedRotationAndTranslation(const mitk::WiiMoteAllDataEvent* wiiMoteEvent) { Geometry3D* geometry = this->TransformCurrentDataInGeometry3D(); m_OrientationX = wiiMoteEvent->GetOrientationX(); m_OrientationY = wiiMoteEvent->GetOrientationY(); m_OrientationZ = wiiMoteEvent->GetOrientationZ(); ScalarType pitchSpeed = wiiMoteEvent->GetPitchSpeed(); ScalarType rollSpeed = wiiMoteEvent->GetRollSpeed(); ScalarType yawSpeed = wiiMoteEvent->GetYawSpeed(); // angle x if(std::abs(pitchSpeed) < 200) pitchSpeed = 0; m_xAngle += (pitchSpeed / 1500); // angle y if(std::abs(rollSpeed) < 200) rollSpeed = 0; m_yAngle += (rollSpeed / 1500); // angle z if(std::abs(yawSpeed) < 200) yawSpeed = 0; m_zAngle += (yawSpeed / 1500); if( std::abs(pitchSpeed) > 200 || std::abs(rollSpeed) > 200 || std::abs(yawSpeed) > 200) { m_InRotation = true; //// depending on a combination of the //// orientation the angleX wil be altered //// because the range from roll is limited //// range: -90° to 90° by the wiimote //if(wiiMoteEvent->GetOrientationZ() < 0) //{ // // value is positive // if(wiiMoteEvent->GetOrientationX() > 0) // { // // the degree measured decreases after it reaches // // in the "real" world the 90 degree angle // // (rotation to the right side) // // therefore it needs to artificially increased // // measured value drops -> computated angle increases // angleX = 90 - angleX; // // now add the "new" angle to 90 degree threshold // angleX += 90; // } // // value is negative // else if(wiiMoteEvent->GetOrientationX() < 0) // { // // the degree measured increases after it reaches // // in the "real" world -90 degree // // (rotation to the left side) // // therefore it needs to be artificially decreased // // (example -90 -> -70, but -110 is needed) // // measured value increases -> computated angle decreases // angleX = 90 + angleX; // // invert the algebraic sign, because it is the "negative" // // side of the rotation // angleX = -angleX; // // now add the negative value to the -90 degree threshold // // to decrease the value further // angleX -= 90; // } // else if(wiiMoteEvent->GetOrientationX() == 0) // { // // i.e. wiimote is flipped upside down // angleX = 180; // } //} //rotation vtkTransform *vtkTransform = vtkTransform::New(); //copy m_vtkMatrix to m_VtkIndexToWorldTransform geometry->TransferItkToVtkTransform(); //////m_VtkIndexToWorldTransform as vtkLinearTransform* vtkTransform->SetMatrix(geometry->GetVtkTransform()->GetMatrix()); // rotation from center is different // from rotation while translated // hence one needs the center of the object Point3D center = geometry->GetOrigin(); vtkTransform->PostMultiply(); vtkTransform->Translate(-center[0], -center[1], -center[2]); //vtkTransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]); vtkTransform->RotateX(m_xAngle); vtkTransform->RotateY(m_zAngle); vtkTransform->RotateZ(m_yAngle); vtkTransform->Translate(center[0], center[1], center[2]); vtkTransform->PreMultiply(); geometry->SetIndexToWorldTransformByVtkMatrix(vtkTransform->GetMatrix()); geometry->Modified(); // indicate modification of data tree node m_DataNode->Modified(); vtkTransform->Delete(); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else if(!m_InRotation) { float xValue = wiiMoteEvent->GetXAcceleration(); float yValue = wiiMoteEvent->GetYAcceleration(); float zValue = wiiMoteEvent->GetZAcceleration(); float pitch = wiiMoteEvent->GetPitch(); float roll = wiiMoteEvent->GetRoll(); // substracts the proportionate force // applied by gravity depending on the // orientation float sinP = sin(pitch/180.0 * M_PI); float cosP = cos(pitch/180.0 * M_PI); float sinR = sin(roll/180.0 * M_PI); float cosR = cos(roll/180.0 * M_PI); // x acceleration if(m_OrientationZ >= 0) xValue = xValue - sinR * cosP; else xValue = xValue + sinR * cosP; // against drift if(std::abs(xValue) < 0.2) xValue = 0; // y acceleration yValue = yValue + sinP; // against drift if(std::abs(yValue) < 0.2) yValue = 0; // z acceleration zValue = zValue - cosP * cosR; // against drift if(std::abs(zValue) < 0.3) zValue = 0; // simple integration over time // resulting in velocity switch(m_TranslationMode) { case 1: m_xVelocity -= xValue; m_yVelocity -= yValue; m_zVelocity += zValue; // 1 = movement to the right // initially starts with negative acceleration // 2 = movement to the left // initially starts with positive acceleration if( m_xVelocity > 0 && xValue > 0 // 1 || m_xVelocity < 0 && xValue < 0) // 2 { m_xVelocity += xValue; } else if( m_xVelocity > 0 && xValue < 0 // 1 || m_xVelocity < 0 && xValue > 0) // 2 { m_xVelocity -= xValue; } break; case 3: m_yVelocity -= yValue; break; case 4: // 1 = movement up // initially starts with positive acceleration // 2 = movement down // initially starts with negative acceleration if( m_zVelocity > 0 && zValue < 0 // 1 || m_zVelocity < 0 && zValue > 0) // 2 { m_zVelocity -= zValue; } else if(m_zVelocity > 0 && zValue > 0 // 1 || m_zVelocity < 0 && zValue < 0) // 2 { m_zVelocity += zValue; } break; } // sets the mode of the translation // depending on the initial velocity if( std::abs(m_xVelocity) > std::abs(m_yVelocity) && std::abs(m_xVelocity) > std::abs(m_zVelocity) ) { m_TranslationMode = 2; m_yVelocity = 0; m_zVelocity = 0; } else if( std::abs(m_yVelocity) > std::abs(m_xVelocity) && std::abs(m_yVelocity) > std::abs(m_zVelocity) ) { m_TranslationMode = 3; m_xVelocity = 0; m_zVelocity = 0; } else if(std::abs(m_zVelocity) > std::abs(m_xVelocity) && std::abs(m_zVelocity) > std::abs(m_yVelocity) ) { m_TranslationMode = 4; m_xVelocity = 0; m_yVelocity = 0; } // translation mitk::Vector3D movementVector; movementVector.SetElement(0,m_xVelocity); movementVector.SetElement(1,m_yVelocity); movementVector.SetElement(2,m_zVelocity); geometry->Translate(movementVector); // indicate modification of data tree node m_DataNode->Modified(); // update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.h b/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.h index 4151c7fcae..701e60e309 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteInteractor.h @@ -1,88 +1,103 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEINTERACTOR_H #define MITK_WIIMOTEINTERACTOR_H // mitk #include #include #include #include #include #include #include // export macro #include namespace mitk { class mitkWiiMote_EXPORT WiiMoteInteractor: public mitk::Interactor { public: // SmartPointer macros mitkClassMacro(WiiMoteInteractor, Interactor); mitkNewMacro2Param(Self, const char*, DataNode*); protected: // SmartPointer conventions WiiMoteInteractor(const char* type, DataNode* dataNode); virtual ~WiiMoteInteractor(); // allow movement virtual bool OnWiiMoteResetButton(Action* action, const mitk::StateEvent* event); // movement virtual bool OnWiiMoteInput(Action* action, const mitk::StateEvent* event); // stopping movement virtual bool OnWiiMoteReleaseButton(Action* action, const mitk::StateEvent* event); private: mitk::Geometry3D* TransformCurrentDataInGeometry3D(); // all movements are separated and fixed bool FixedRotationAndTranslation(const mitk::WiiMoteAllDataEvent* event); vnl_matrix_fixed ComputeCurrentCameraPosition(vtkCamera* vtkCamera); // combined movements and different interaction modes bool DynamicRotationAndTranslation(Geometry3D* geometry); float m_OrientationX; float m_OrientationY; float m_OrientationZ; float m_xVelocity; float m_yVelocity; float m_zVelocity; float m_xValue; float m_yValue; float m_zValue; // refering to an angle around an axis // which is defined in the wiimote ScalarType m_xAngle; ScalarType m_yAngle; ScalarType m_zAngle; // modes bool m_InRotation; int m_TranslationMode; // default: 1 = relative to object // 2 = relative to camera view int m_SurfaceInteractionMode; // to reset the geometry mitk::Geometry3D::Pointer m_OriginalGeometry; mitk::BaseRenderer::Pointer m_BaseRenderer; }; } #endif // MITK_WIIMOTEINTERACTOR_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.cpp index 6562b33091..6e0afe33b9 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.cpp @@ -1,32 +1,47 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteMultiIREvent.h" mitk::WiiMoteMultiIREvent::WiiMoteMultiIREvent(mitk::Point3D Coordinate3D) : Event(NULL, mitk::Type_WiiMoteInput, mitk::BS_NoButton, mitk::BS_NoButton, Key_none) { m_3DCoordinate = Coordinate3D; } mitk::WiiMoteMultiIREvent::~WiiMoteMultiIREvent() { } mitk::Point3D mitk::WiiMoteMultiIREvent::Get3DCoordinate() const { return m_3DCoordinate; } const char* mitk::WiiMoteMultiIREvent::GetEventName() const { return "WiiMoteMultiIREvent"; } bool mitk::WiiMoteMultiIREvent::CheckEvent(const itk::EventObject *e) const { return dynamic_cast(e); } itk::EventObject* mitk::WiiMoteMultiIREvent::MakeObject() const { return new Self(m_3DCoordinate); } \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.h b/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.h index caf73fb024..463d99fb03 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteMultiIREvent.h @@ -1,38 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEMULTIIREVENT_H #define MITK_WIIMOTEMULITIREVENT_H #include "mitkInputDevicesExports.h" #include "mitkEvent.h" #include "mitkVector.h" #include "mitkInteractionConst.h" namespace mitk { class mitkInputDevices_EXPORT WiiMoteMultiIREvent : public Event, itk::EventObject { public: typedef WiiMoteMultiIREvent Self; typedef itk::EventObject Superclass; WiiMoteMultiIREvent(mitk::Point3D Coordinate3D); ~WiiMoteMultiIREvent(); mitk::Point3D Get3DCoordinate() const; //itk::EventObject implementation const char * GetEventName() const; bool CheckEvent(const ::itk::EventObject* e) const; ::itk::EventObject* MakeObject() const; protected: private: mitk::Point3D m_3DCoordinate; }; // end class } // end namspace #endif // MITK_WIIMOTEMULITIREVENT_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteThread.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteThread.cpp index fb9b67729d..27f66f3bbf 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteThread.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteThread.cpp @@ -1,647 +1,662 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include #include #include #include #include #include #include // timelimit between two state changes to send an event // the chosen value is empirical const double TIMELIMIT = 0.5; const int MAX_WIIMOTES = 4; mitk::WiiMoteThread::WiiMoteThread() : m_MultiThreader(itk::MultiThreader::New()) , m_WiiMoteThreadFinished(itk::FastMutexLock::New()) , m_StopWiiMote(false) , m_ThreadID(-1) , m_LastRecordTime(0) , m_ReadDataOnce(false) , m_InCalibrationMode(false) , m_SurfaceInteraction(false) , m_ButtonBPressed(false) , m_SurfaceInteractionMode(1) , m_Kalman(mitk::KalmanFilter::New()) { m_Kalman->SetMeasurementNoise( 0.3 ); m_Kalman->SetProcessNoise( 1 ); m_Kalman->ResetFilter(); // used for measuring movement m_TimeStep = 0; } mitk::WiiMoteThread::~WiiMoteThread() { for(int i = 0; i < m_NumberDetectedWiiMotes;i++) { if(m_WiiMotes[i].IsConnected()) { m_WiiMotes[i].Disconnect(); } } } void mitk::WiiMoteThread::OnStateChange( wiimote &remote , state_change_flags changed , const wiimote_state &newState) { // a MotionPlus was detected if(changed & MOTIONPLUS_DETECTED) { // enable it if there isn't a normal extension plugged into it // (MotionPlus devices don't report like normal extensions until // enabled - and then, other extensions attached to it will no longer be // reported (so disable the M+ when you want to access them again). if(remote.ExtensionType == wiimote_state::NONE) { if(remote.EnableMotionPlus()) { MITK_INFO << "Motion Plus enabled"; } } } else if(changed & EXTENSION_CONNECTED) { // switch to a report mode that includes the extension data (we will // loose the IR dot sizes) // note: there is no need to set report types for a Balance Board. if(!remote.IsBalanceBoard()) { remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR_EXT); } } } void mitk::WiiMoteThread::Run() { m_ThreadID = m_MultiThreader->SpawnThread(this->StartWiiMoteThread, this); } ITK_THREAD_RETURN_TYPE mitk::WiiMoteThread::StartWiiMoteThread(void* pInfoStruct) { // extract this pointer from Thread Info structure struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) return ITK_THREAD_RETURN_VALUE; if (pInfo->UserData == NULL) return ITK_THREAD_RETURN_VALUE; mitk::WiiMoteThread* wiiMoteThread = static_cast(pInfo->UserData); if (wiiMoteThread != NULL) wiiMoteThread->StartWiiMote(); return ITK_THREAD_RETURN_VALUE; } void mitk::WiiMoteThread::StartWiiMote() { // transfers the execution rights to the WiiMote thread m_WiiMoteThreadFinished->Lock(); // is needed in case the Wiimote was deactivated // while the application is running this->m_StopWiiMote = false; // transfers the execution rights back to the main thread m_WiiMoteThreadFinished->Unlock(); while(CONNECTED && !m_StopWiiMote) { m_WiiMoteThreadFinished->Lock(); if(this->DetectWiiMotes()) { break; } m_WiiMoteThreadFinished->Unlock(); } if(this->m_NumberDetectedWiiMotes <= 1) { this->SingleWiiMoteUpdate(); } else { this->MultiWiiMoteUpdate(); } //if(m_WiiMote.IsConnected() && m_StopWiiMote) //{ //clean up //m_WiiMoteThreadFinished->Lock(); //m_WiiMote.Disconnect(); //m_WiiMoteThreadFinished->Unlock(); //MITK_INFO << "WiiMote disconnected.."; //} this->DisconnectWiiMotes(); return; } void mitk::WiiMoteThread::StopWiiMote() { this->m_StopWiiMote = true; } void mitk::WiiMoteThread::ReconnectWiiMote() { if(m_WiiMotes[0].Connect(wiimote::FIRST_AVAILABLE)) { MITK_INFO << "WiiMote reconnected.."; } } bool mitk::WiiMoteThread::DetectWiiMotes() { bool result = false; unsigned detected = 0; unsigned connectionTrys = 0; while(detected < 5) { connectionTrys++; if(!m_WiiMotes[detected].Connect(wiimote::FIRST_AVAILABLE)) { if(connectionTrys > 5) { break; } } else { MITK_INFO << "WiiMote detected :: Assigned ID: " << detected; switch(detected) { // 0x00 none // 0x0f all leds // 0x01 first led // 0x02 second led // 0x03 third led // 0x04 fourth led case 0: m_WiiMotes[detected].SetLEDs(0x01); break; case 1: m_WiiMotes[detected].SetLEDs(0x02); break; case 2: m_WiiMotes[detected].SetLEDs(0x03); break; case 3: m_WiiMotes[detected].SetLEDs(0x04); break; } // ---------------- unclean solution, missing generic approach --------------------- // uses state-change callback to get notified of extension-related // events OnStateChange must be static, otherwise the this-operator // will be used and this callback can't convert it into the typedef // defined in the wiiyourself library m_WiiMotes[0].ChangedCallback = &mitk::WiiMoteThread::OnStateChange; // allows flags to trigger a state change m_WiiMotes[0].CallbackTriggerFlags = (state_change_flags) (CONNECTED | EXTENSION_CHANGED | MOTIONPLUS_CHANGED); m_WiiMotes[0].SetReportType(wiimote::IN_BUTTONS_ACCEL_IR); // fixes the problem while in release // the Motion Plus cannot be connected // with the state change if(!m_WiiMotes[0].MotionPlusEnabled() && m_WiiMotes[0].MotionPlusConnected()) { m_WiiMotes[0].EnableMotionPlus(); m_WiiMotes[0].SetReportType(wiimote::IN_BUTTONS_ACCEL_IR_EXT); } // ----------------------------------- END --------------------------------------- detected++; connectionTrys = 0; result = true; } // end else itksys::SystemTools::Delay(500); } // end while m_NumberDetectedWiiMotes = detected; return result; } void mitk::WiiMoteThread::DisconnectWiiMotes() { for(int i = 0; i < m_NumberDetectedWiiMotes;i++) { this->m_WiiMotes[i].Disconnect(); } MITK_INFO << "Wiimotes disconnected"; } void mitk::WiiMoteThread::WiiMoteIRInput() { if( m_WiiMotes[0].IR.Dot[0].bVisible /* && m_WiiMotes[0].IR.Dot[1].bVisible*/ ) { m_Command = ReceptorCommand::New(); m_Command->SetCallbackFunction ( mitk::WiiMoteAddOn::GetInstance() , &mitk::WiiMoteAddOn::WiiMoteInput ); double tempTime(itksys::SystemTools::GetTime()); float inputCoordinates[2] = {m_WiiMotes[0].IR.Dot[0].RawX, m_WiiMotes[0].IR.Dot[0].RawY}; mitk::Point2D tempPoint(inputCoordinates); int sliceValue = 0; if(m_WiiMotes[0].IR.Dot[1].bVisible) { sliceValue = ( m_WiiMotes[0].IR.Dot[1].RawY ); } // if the last read data is not valid, // because the thread was not started if(!m_ReadDataOnce) { m_ReadDataOnce = true; } else // there is old data available - calculate the movement and send event { // this time constraint allows the user to move the camera // with the IR sender (by switching the IR source on and off) // similiar to a mouse (e.g. if you lift the mouse from the // surface and put it down again on another position, there // was no input. Now the input starts again and the movement // will begin from the last location of the mouse, although // the physical position of the mouse changed.) if ((tempTime-m_LastRecordTime) < TIMELIMIT) { mitk::Vector2D resultingVector(m_LastReadData-tempPoint); mitk::WiiMoteIREvent e(resultingVector, tempTime, sliceValue); mitk::CallbackFromGUIThread::GetInstance() ->CallThisFromGUIThread(m_Command, e.MakeObject()); } } m_LastRecordTime = tempTime; m_LastReadData = tempPoint; } } void mitk::WiiMoteThread::WiiMoteButtonPressed(int buttonType) { m_Command = ReceptorCommand::New(); m_Command->SetCallbackFunction ( mitk::WiiMoteAddOn::GetInstance() , &mitk::WiiMoteAddOn::WiiMoteButtonPressed ); mitk::WiiMoteButtonEvent e ( mitk::Type_WiiMoteButton , mitk::BS_NoButton , mitk::BS_NoButton , buttonType ); mitk::CallbackFromGUIThread::GetInstance() ->CallThisFromGUIThread(m_Command, e.MakeObject()); } void mitk::WiiMoteThread::WiiMoteButtonReleased(int buttonType) { m_Command = ReceptorCommand::New(); m_Command->SetCallbackFunction ( mitk::WiiMoteAddOn::GetInstance() , &mitk::WiiMoteAddOn::WiiMoteButtonReleased ); mitk::WiiMoteButtonEvent e ( mitk::Type_WiiMoteButton , mitk::BS_NoButton , mitk::BS_NoButton , buttonType ); mitk::CallbackFromGUIThread::GetInstance() ->CallThisFromGUIThread(m_Command, e.MakeObject()); } void mitk::WiiMoteThread::WiiMoteCalibrationInput() { if(m_WiiMotes[0].IR.Dot[0].bVisible) { m_Command = ReceptorCommand::New(); m_Command->SetCallbackFunction ( mitk::WiiMoteAddOn::GetInstance() , &mitk::WiiMoteAddOn::WiiMoteCalibrationInput ); mitk::WiiMoteCalibrationEvent e ( m_WiiMotes[0].IR.Dot[0].RawX , m_WiiMotes[0].IR.Dot[0].RawY ); mitk::CallbackFromGUIThread::GetInstance() ->CallThisFromGUIThread(m_Command, e.MakeObject()); } } void mitk::WiiMoteThread::SingleWiiMoteUpdate() { // update and settings process // the minus button is a manual abort criteria // it can be chosen differently, if needed while(!m_WiiMotes[0].Button.Minus() && !m_StopWiiMote) { m_WiiMoteThreadFinished->Lock(); // refreshes the state of the wiimote // do not remove while(m_WiiMotes[0].RefreshState() == NO_CHANGE) { itksys::SystemTools::Delay(1); } m_WiiMoteThreadFinished->Unlock(); m_WiiMoteThreadFinished->Lock(); if(!m_SurfaceInteraction) { if(!m_InCalibrationMode) { this->WiiMoteIRInput(); } else { this->WiiMoteCalibrationInput(); } if(m_WiiMotes[0].Button.Home()) this->WiiMoteButtonPressed(mitk::Key_Home); if(m_WiiMotes[0].Button.A()) { this->WiiMoteButtonPressed(mitk::Key_A); // necessary to avoid sending the movement vector // instead of the raw coordinates for the calibration if(this->m_InCalibrationMode) { this->m_InCalibrationMode = false; } else { this->m_InCalibrationMode = true; } itksys::SystemTools::Delay(3000); } } else { // to be able to distinguish whether // the button B was pressed is now released; // state changes are defined in the StateMachine.xml // files if(m_WiiMotes[0].Button.B()) { // case 1: button is now pressed and // was pressed before -> still surface // interaction if(m_ButtonBPressed) { this->SurfaceInteraction(); } // case 2: button is now pressed and // was not pressed before -> allow surface // interaction else { this->WiiMoteButtonPressed(mitk::Key_B); // needed to set it true for the first // time after a release or at the start // of the application m_ButtonBPressed = true; } } else { // case 3: button is not pressed and // was pressed before -> stop surface // interaction if(m_ButtonBPressed) { this->WiiMoteButtonReleased(mitk::Key_B); m_ButtonBPressed = false; // reset to measure new movement m_TimeStep = 0; } // case 4: button is not pressed and // was not pressed before -> no change } //// used for measurements //// start //if(m_WiiMotes[0].Button.B()) //{ // if(!m_ButtonBPressed) // { // m_ButtonBPressed = true; // } //} //// stop //if(m_WiiMotes[0].Button.A()) //{ // if(m_ButtonBPressed) // { // m_ButtonBPressed = false; // m_TimeStep = 0; // itksys::SystemTools::Delay(1000); // } //} //// recording //if(m_ButtonBPressed) //{ // this->SurfaceInteraction(); //} // reset object if(m_WiiMotes[0].Button.Home()) this->WiiMoteButtonPressed(mitk::Key_Home); // interaction modes // surface interaction relative to object if(m_WiiMotes[0].Button.One()) this->m_SurfaceInteractionMode = 1; // surface interaction relative to camera if(m_WiiMotes[0].Button.Two()) this->m_SurfaceInteractionMode = 2; } m_WiiMoteThreadFinished->Unlock(); if(m_WiiMotes[0].ConnectionLost()) { m_WiiMoteThreadFinished->Lock(); this->ReconnectWiiMote(); m_WiiMoteThreadFinished->Unlock(); } } } void mitk::WiiMoteThread::MultiWiiMoteUpdate() { // update and settings process while(!m_WiiMotes[0].Button.Minus() && !m_StopWiiMote ) { m_WiiMoteThreadFinished->Lock(); // refreshes the state of the wiimotes // do not remove while(m_WiiMotes[0].RefreshState() == NO_CHANGE && m_WiiMotes[1].RefreshState() == NO_CHANGE) { itksys::SystemTools::Delay(1); } m_WiiMoteThreadFinished->Unlock(); m_WiiMoteThreadFinished->Lock(); if(!m_InCalibrationMode) { this->MultiWiiMoteIRInput(); } else { // calibration } m_WiiMoteThreadFinished->Unlock(); if(m_WiiMotes[0].Button.A()) { this->WiiMoteButtonPressed(mitk::Key_A); if(this->m_InCalibrationMode) { this->m_InCalibrationMode = false; } else { this->m_InCalibrationMode = true; } itksys::SystemTools::Delay(3000); } } // end while } void mitk::WiiMoteThread::MultiWiiMoteIRInput() { // testing multiple wiimotes if(m_WiiMotes[0].IR.Dot[0].bVisible && m_WiiMotes[1].IR.Dot[0].bVisible) { float inputCoordinates[2] = {m_WiiMotes[0].IR.Dot[0].RawX, m_WiiMotes[0].IR.Dot[0].RawY}; mitk::Point2D tempPoint(inputCoordinates); float inputCoordinates2[2] = {m_WiiMotes[1].IR.Dot[0].RawX, m_WiiMotes[1].IR.Dot[0].RawY}; mitk::Point2D tempPoint2(inputCoordinates2); mitk::Vector2D result = (tempPoint2 - tempPoint); MITK_INFO << "IR1 :: X: " << tempPoint[0]; MITK_INFO << "IR1 :: Y: " << tempPoint[1]; MITK_INFO << "IR2 :: X: " << tempPoint2[0]; MITK_INFO << "IR2 :: Y: " << tempPoint2[1]; } } void mitk::WiiMoteThread::SetWiiMoteSurfaceIModus(bool active) { this->m_SurfaceInteraction = active; } void mitk::WiiMoteThread::SurfaceInteraction() { m_Command = ReceptorCommand::New(); m_Command->SetCallbackFunction ( mitk::WiiMoteAddOn::GetInstance() , &mitk::WiiMoteAddOn::WiiMoteSurfaceInteractionInput ); mitk::WiiMoteAllDataEvent e ( mitk::Type_WiiMoteInput , m_WiiMotes[0].MotionPlus.Speed.Pitch , m_WiiMotes[0].MotionPlus.Speed.Roll , m_WiiMotes[0].MotionPlus.Speed.Yaw , m_WiiMotes[0].Acceleration.Orientation.X , m_WiiMotes[0].Acceleration.Orientation.Y , m_WiiMotes[0].Acceleration.Orientation.Z , m_WiiMotes[0].Acceleration.Orientation.Roll , m_WiiMotes[0].Acceleration.Orientation.Pitch , m_WiiMotes[0].Acceleration.X , m_WiiMotes[0].Acceleration.Y , m_WiiMotes[0].Acceleration.Z , m_SurfaceInteractionMode ); //float test = m_Kalman->ProcessValue( m_WiiMotes[0].Acceleration.Z ); mitk::CallbackFromGUIThread::GetInstance() ->CallThisFromGUIThread(m_Command, e.MakeObject()); //double tempTime(itksys::SystemTools::GetTime()); //double diff = tempTime - m_LastRecordTime; // //MITK_INFO << "Speed Pitch: " << m_WiiMotes[0].MotionPlus.Speed.Pitch; //MITK_INFO << "Speed Roll: " << m_WiiMotes[0].MotionPlus.Speed.Roll; //MITK_INFO << "Speed Yaw: " << m_WiiMotes[0].MotionPlus.Speed.Yaw; //MITK_INFO << "Speed X: " << m_WiiMotes[0].Acceleration.X; //MITK_INFO << "Speed Y: " << m_WiiMotes[0].Acceleration.Y; //MITK_INFO << "Speed Z: " << m_WiiMotes[0].Acceleration.Z; //MITK_INFO << "Time difference: " << diff; //if(m_TimeStep <= 400) //{ // std::ofstream file; // file.open("C:/WiiMotionData/motion.txt",ios::app); // file << m_TimeStep << " " // << m_WiiMotes[0].Acceleration.X << " " // << m_WiiMotes[0].Acceleration.Y << " " // << m_WiiMotes[0].Acceleration.Z << " " // << m_WiiMotes[0].MotionPlus.Speed.Pitch << " " // << m_WiiMotes[0].MotionPlus.Speed.Yaw << " " // << m_WiiMotes[0].MotionPlus.Speed.Roll << " " // << m_WiiMotes[0].Acceleration.Orientation.X << " " // << m_WiiMotes[0].Acceleration.Orientation.Y << " " // << m_WiiMotes[0].Acceleration.Orientation.Z << " " // << m_WiiMotes[0].Acceleration.Orientation.Pitch << " " // << m_WiiMotes[0].Acceleration.Orientation.Roll << " " // << std::endl; // file.close(); // // remove, if not needed // // otherwise this will eventually // // disable correct functionality of Headtracking // // since it's using its m_LastRecordTime // //m_LastRecordTime = tempTime; // m_TimeStep++; //} } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteThread.h b/Modules/InputDevices/WiiMote/mitkWiiMoteThread.h index 2eef0bb8dc..295a099dc7 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteThread.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteThread.h @@ -1,203 +1,218 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEHTREAD_H #define MITK_WIIMOTEHTREAD_H #include "wiimote.h" // mitk #include "mitkCommon.h" #include "mitkCallbackFromGUIThread.h" #include "mitkVector.h" #include "mitkKalmanFilter.h" // itk #include "itkObject.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" #include "itksys/SystemTools.hxx" // used for GetTime() and Delay(); namespace mitk { // instead of include, enables this class to know the addon class WiiMoteAddOn; class WiiMoteThread : public itk::Object { public: // typedefs are used in context with CallbackFromGUIThread typedef itk::ReceptorMemberCommand ReceptorCommand; // eventually probs with Linux -> typename typedef ReceptorCommand::Pointer ReceptorCommandPointer; WiiMoteThread(); ~WiiMoteThread(); /** * Allows to set report types, detects extensions and responds to connect/disconnect
* events of extension, such as MotionPlus. * * NOTE: don't access the public state from the 'remote' object here, as it will * be out-of-date (it's only updated via RefreshState() calls, and these * are reserved for the main application so it can be sure the values * stay consistent between calls). Instead query 'new_state' only. * * @param remote * the old state of the connected Wii remote * @param changed * the state change of the Wii remote * @param newState * the new state, after the change is applied (i.e. new extension connected) * */ static void OnStateChange(wiimote &remote, state_change_flags changed, const wiimote_state &newState); /** * Starts the thread for the Wiimote. */ void Run(); /** * Helper function, because the itk::MultiThreader can only
* start a new thread with a static member function. */ static ITK_THREAD_RETURN_TYPE StartWiiMoteThread(void* data); /** * Connects the Wiimote and allows access to its functionality. */ void StartWiiMote(); /** * Stops the running thread. */ void StopWiiMote(); /** * Reconnects the Wiimote in case the connection is lost. */ void ReconnectWiiMote(); /** * Detects all available Wiimotes. * * TODO: more detailed regarding the mode and led lighting */ bool DetectWiiMotes(); /** * Disconnects all connected Wiimotes. */ void DisconnectWiiMotes(); /** * Reads incoming data from the IR camera. After processing the data
* (e.g. computations, assigning commands...) fires Wiimote events accordingly. * */ void WiiMoteIRInput(); /** * Reads incoming data from buttons. After processing the data
* (e.g. computations, assigning commands...) fires Wiimote events
* that indicate a button was pressed. * * @param buttonType * the type of button, that was used to trigger this event */ void WiiMoteButtonPressed(int buttonType); /** * Reads incoming data from buttons. After processing the data
* (e.g. computations, assigning commands...) fires Wiimote events
* that indicate a button release. * * @param buttonType * the type of button, that was used to trigger this event */ void WiiMoteButtonReleased(int buttonType); /** * Reads incoming data from the IR camera. Afterwards the raw x and y coordinates
* are stored in an event and fired as an event. * */ void WiiMoteCalibrationInput(); /** * Constantly refreshes the state of a single wiimote. Also changes between
* the calibration mode and the IR input mode through button push. * * TODO: more detailed explanation of calibration * */ void SingleWiiMoteUpdate(); /** * Constantly refreshes the state of multiple wiimotes. */ void MultiWiiMoteUpdate(); /** * Processes the different IR inputs from multiple wiimotes. */ void MultiWiiMoteIRInput(); /** * Sets the modus for the first connected Wiimote depending
* on the given parameter. * * @param activated * true, the Surface Interaction modus will be activated * false, the Surface Interaction modus will be deactivated */ void SetWiiMoteSurfaceIModus(bool activated); // TODO void SurfaceInteraction(); protected: private: // threading int m_ThreadID; itk::MultiThreader::Pointer m_MultiThreader; // mutex to control the flow of the method StartWiiMote() itk::FastMutexLock::Pointer m_WiiMoteThreadFinished; bool m_StopWiiMote; // access to the wiimote and parameter for callbackfromguithread ReceptorCommandPointer m_Command; // required for computation of movement Point2D m_LastReadData; double m_LastRecordTime; bool m_ReadDataOnce; // modes bool m_InCalibrationMode; bool m_SurfaceInteraction; bool m_ButtonBPressed; // Default: 1 = relative to object // 2 = relative to camera view int m_SurfaceInteractionMode; //store all connected Wiimotes wiimote m_WiiMotes[4]; int m_NumberDetectedWiiMotes; // used for measuring movement int m_TimeStep; // Kalman filter mitk::KalmanFilter::Pointer m_Kalman; }; } #endif // MITK_WIIMOTEHTREAD_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.cpp b/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.cpp index 930fff9f43..6fb89db473 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.cpp +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.cpp @@ -1,422 +1,437 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkWiiMoteVtkCameraController.h" #include "mitkGlobalInteraction.h" #include "mitkInteractionConst.h" #include "mitkStateEvent.h" #include "mitkSurface.h" #include "mitkVtkPropRenderer.h" #include "vtkRenderer.h" #include "vtkCamera.h" // factor derived from the asumption that // the field of view in the virtual reality // is limited to an angle of 45° const double CALIBRATIONFACTORY = 0.125; const double CALIBRATIONFACTORX = 0.125; // max resolution of the cam 1024x768 const double XMIN = 0; const double XMAX = 1024; const double YMIN = 0; const double YMAX = 768; // initial scroll value const int UPDATEFREQUENCY = 5; mitk::WiiMoteVtkCameraController::WiiMoteVtkCameraController() : CameraController("WiiMoteHeadtracking") , m_ClippingRangeIsSet(false) , m_SensitivityXMIN (XMAX) , m_SensitivityXMAX (XMIN) , m_SensitivityYMIN (YMAX) , m_SensitivityYMAX (YMIN) , m_SensitivityX (0) , m_SensitivityY (0) , m_Calibrated (false) , m_TransversalBR( NULL ) , m_InitialScrollValue( 0 ) , m_UpdateFrequency( 0 ) , m_CurrentElevationAngle ( 0 ) , m_CurrentAzimuthAngle ( 0 ) { CONNECT_ACTION(mitk::AcONWIIMOTEINPUT, OnWiiMoteInput); CONNECT_ACTION(mitk::AcRESETVIEW, ResetView); CONNECT_ACTION(mitk::AC_INIT, InitCalibration); CONNECT_ACTION(mitk::AcCHECKPOINT, Calibration); CONNECT_ACTION(mitk::AcFINISH, FinishCalibration); } mitk::WiiMoteVtkCameraController::~WiiMoteVtkCameraController() { } bool mitk::WiiMoteVtkCameraController::OnWiiMoteInput(mitk::Action* a, const mitk::StateEvent* e) { //only if 3D rendering const mitk::BaseRenderer* br = mitk::GlobalInteraction::GetInstance()->GetFocus(); this->SetRenderer( br ); mitk::BaseRenderer::MapperSlotId id = ((mitk::BaseRenderer*)(br))->GetMapperID(); if (id != mitk::BaseRenderer::Standard3D) return true; //only if focused by the FocusManager if (this->GetRenderer() != mitk::GlobalInteraction::GetInstance()->GetFocus()) return true; //pre-checking for safety vtkRenderer* vtkRenderer = ((mitk::VtkPropRenderer*)this->GetRenderer())->GetVtkRenderer(); if (vtkRenderer == NULL) return false; vtkCamera* vtkCam = (vtkCamera*)vtkRenderer->GetActiveCamera(); //TODO check the range if(!m_ClippingRangeIsSet) vtkCam->SetClippingRange(0.1, 1000); const mitk::WiiMoteIREvent* wiiMoteIREvent; if(!(wiiMoteIREvent = dynamic_cast(e->GetEvent()))) { MITK_ERROR << "Not a WiiMote Event!"; return false; } // get data from the Wiimote mitk::Vector2D tempMovementVector(wiiMoteIREvent->GetMovementVector()); float inputCoordinates[3] = {tempMovementVector[0],tempMovementVector[1], 0}; mitk::Vector3D movementVector(inputCoordinates); //compute current sensitivity according to current BoundingBox of the whole scene! double sceneSensivity = 1.0; mitk::DataStorage* ds = m_Renderer->GetDataStorage(); mitk::BoundingBox::Pointer bb = ds->ComputeBoundingBox(); mitk::BoundingBox::AccumulateType length = bb->GetDiagonalLength2(); if (length > 0.00001)//if length not zero sceneSensivity *= 100.0 / (sqrt(length)) ; //sensivity to adapt to mitk speed movementVector *= sceneSensivity; if(!m_Calibrated) { movementVector[0] *= CALIBRATIONFACTORX; movementVector[1] *= CALIBRATIONFACTORY; } else { movementVector[0] *= m_SensitivityX; movementVector[1] *= m_SensitivityY; } // inverts y direction to simulate a 3D View // x direction is already inverted movementVector[1] *= -1; m_CurrentElevationAngle += movementVector[1]; MITK_INFO << "Elevation angle: " << m_CurrentElevationAngle; // avoids flipping of the surface // through the elevation function if(m_CurrentElevationAngle < 70 && m_CurrentElevationAngle > -70) { vtkCam->Elevation((double)movementVector[1]); } else if( m_CurrentElevationAngle > 70 ) { m_CurrentElevationAngle = 70; } else if( m_CurrentElevationAngle < -70 ) { m_CurrentElevationAngle = -70; } m_CurrentAzimuthAngle += movementVector[0]; // avoids spinning of the surface if(m_CurrentAzimuthAngle < 70 && m_CurrentAzimuthAngle > -70) { vtkCam->Azimuth((double)movementVector[0]); } else if( m_CurrentAzimuthAngle > 70 ) { m_CurrentAzimuthAngle = 70; } else if( m_CurrentAzimuthAngle < -70 ) { m_CurrentAzimuthAngle = -70; } ////compute the global space coordinates from the relative mouse coordinate ////first we need the position of the camera //mitk::Vector3D camPosition; //double camPositionTemp[3]; //vtkCam->GetPosition(camPositionTemp); //camPosition[0] = camPositionTemp[0]; camPosition[1] = camPositionTemp[1]; camPosition[2] = camPositionTemp[2]; ////then the upvector of the camera //mitk::Vector3D upCamVector; //double upCamTemp[3]; //vtkCam->GetViewUp(upCamTemp); //upCamVector[0] = upCamTemp[0]; upCamVector[1] = upCamTemp[1]; upCamVector[2] = upCamTemp[2]; //upCamVector.Normalize(); ////then the vector to which the camera is heading at (focalpoint) //mitk::Vector3D focalPoint; //double focalPointTemp[3]; //vtkCam->GetFocalPoint(focalPointTemp); //focalPoint[0] = focalPointTemp[0]; focalPoint[1] = focalPointTemp[1]; focalPoint[2] = focalPointTemp[2]; //mitk::Vector3D focalVector; //focalVector = focalPoint - camPosition; //focalVector.Normalize(); ////orthogonal vector to focalVector and upCamVector //mitk::Vector3D crossVector; //crossVector = CrossProduct(upCamVector, focalVector); //crossVector.Normalize(); ////now we have the current orientation so we can adapt it according to the current information, which we got from the Wiimote ////new position of the camera: ////left/right = camPosition + crossVector * movementVector[0]; //mitk::Vector3D vectorX = crossVector * -movementVector[0]; //changes the magnitude, not the direction //double nextCamPosition[3]; //nextCamPosition[0] = camPosition[0] + vectorX[0]; //nextCamPosition[1] = camPosition[1] + vectorX[1]; //nextCamPosition[2] = camPosition[2] + vectorX[2]; ////now the up/down movement //mitk::Vector3D vectorY = upCamVector * movementVector[1]; //changes the magnitude, not the direction //nextCamPosition[0] += vectorY[0]; //nextCamPosition[1] += vectorY[1]; //nextCamPosition[2] += vectorY[2]; ////forward/backward movement //mitk::Vector3D vectorZ = focalVector * -movementVector[2]; //changes the magnitude, not the direction //nextCamPosition[0] += vectorZ[0]; //nextCamPosition[1] += vectorZ[1]; //nextCamPosition[2] += vectorZ[2]; ////set the next position //double nextPosition[3]; //nextPosition[0] = nextCamPosition[0]; nextPosition[1] = nextCamPosition[1]; nextPosition[2] = nextCamPosition[2]; //vtkCam->SetPosition(nextPosition); ////adapt the focal point the same way //double currentFocalPoint[3], nextFocalPoint[3]; //vtkCam->GetFocalPoint(currentFocalPoint); //nextFocalPoint[0] = currentFocalPoint[0] + vectorX[0] + vectorY[0] + vectorZ[0]; //nextFocalPoint[1] = currentFocalPoint[1] + vectorX[1] + vectorY[1] + vectorZ[1]; ; //nextFocalPoint[2] = currentFocalPoint[2] + vectorX[2] + vectorY[2] + vectorZ[2]; //vtkCam->SetFocalPoint(nextFocalPoint); //Reset the camera clipping range based on the bounds of the visible actors. //This ensures that no props are cut off vtkRenderer->ResetCameraClippingRange(); // ------------ transversal scrolling ----------------------- // get renderer const RenderingManager::RenderWindowVector& renderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); for ( RenderingManager::RenderWindowVector::const_iterator iter = renderWindows.begin(); iter != renderWindows.end(); ++iter ) { if ( mitk::BaseRenderer::GetInstance((*iter))->GetMapperID() == BaseRenderer::Standard2D ) { if( mitk::BaseRenderer::GetInstance((*iter))->GetSliceNavigationController() ->GetViewDirection() == mitk::SliceNavigationController::ViewDirection::Transversal ) { m_TransversalBR = mitk::BaseRenderer::GetInstance((*iter)); } } } SlicedGeometry3D* slicedWorldGeometry = dynamic_cast (m_TransversalBR->GetSliceNavigationController()->GetCreatedWorldGeometry()->GetGeometry3D(m_TimeStep)); int numberOfSlices = slicedWorldGeometry->GetSlices(); const mitk::Geometry2D* currentGeo = m_TransversalBR->GetCurrentWorldGeometry2D(); mitk::Point3D origin = currentGeo->GetOrigin(); int sliceValue = wiiMoteIREvent->GetSliceNavigationValue(); if(sliceValue > 0) { if(m_InitialScrollValue == 0) { m_InitialScrollValue = sliceValue; } else if(std::abs(m_InitialScrollValue - sliceValue) > 10) { if(m_UpdateFrequency == UPDATEFREQUENCY /* 5 */) { int steppingValue; int currentPos = origin.GetElement(2); if(sliceValue < m_InitialScrollValue) { /* steppingValue = m_InitialScrollValue - sliceValue; */ steppingValue = currentGeo->GetSpacing()[2]; origin.SetElement(2, currentPos-steppingValue); } else if(sliceValue > m_InitialScrollValue) { /* steppingValue = sliceValue - m_InitialScrollValue;*/ steppingValue = currentGeo->GetSpacing()[2]; origin.SetElement(2, currentPos+steppingValue); } m_UpdateFrequency = 0; } else { m_UpdateFrequency++; } } } else { m_InitialScrollValue = 0; } m_TransversalBR->GetSliceNavigationController()->SelectSliceByPoint(origin); mitk::RenderingManager::GetInstance() ->RequestUpdateAll(); return true; } bool mitk::WiiMoteVtkCameraController::ResetView(mitk::Action *a, const mitk::StateEvent *e) { //reset the camera, so that the objects shown in the scene can be seen. const mitk::VtkPropRenderer* glRenderer = dynamic_cast(m_Renderer); if (glRenderer) { vtkRenderer* vtkRenderer = glRenderer->GetVtkRenderer(); mitk::DataStorage* ds = m_Renderer->GetDataStorage(); if (ds == NULL) return false; mitk::BoundingBox::Pointer bb = ds->ComputeBoundingBox(); mitk::Point3D middle = bb->GetCenter(); vtkRenderer->GetActiveCamera()->SetFocalPoint(middle[0],middle[1],middle[2]); vtkRenderer->ResetCamera(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } bool mitk::WiiMoteVtkCameraController::InitCalibration(mitk::Action *a, const mitk::StateEvent *e) { // to initialize the values with its counterpart // is essential. The reason is that through calibration // the values will increase or decrease depending on // semantics: // the max will try to reach the XMAX (from XMIN) // the min will try to reach the XMIN (from XMAX) // i.e. in the calibration process they move // into their opposite direction to create an // intervall that defines the boundaries m_SensitivityX = 0; m_SensitivityXMAX = XMIN; m_SensitivityXMIN = XMAX; m_SensitivityY = 0; m_SensitivityYMAX = YMIN; m_SensitivityYMIN = YMAX; this->m_Calibrated = false; MITK_INFO << "Starting calibration - other wiimote functionality deactivated."; return true; } bool mitk::WiiMoteVtkCameraController::Calibration(mitk::Action *a, const mitk::StateEvent *e) { const mitk::WiiMoteCalibrationEvent* WiiMoteCalibrationEvent; if(!(WiiMoteCalibrationEvent = dynamic_cast(e->GetEvent()))) { MITK_ERROR << "Not a WiiMote Event!"; return false; } double tempX(WiiMoteCalibrationEvent->GetXCoordinate()); double tempY(WiiMoteCalibrationEvent->GetYCoordinate()); MITK_INFO << "Raw X: " << tempX; MITK_INFO << "Raw Y: " << tempY; // checks first whether the incoming data is valid if(XMIN < tempX && tempX < XMAX) { if(tempX > m_SensitivityXMAX) { m_SensitivityXMAX = tempX; } else if(tempX < m_SensitivityXMIN) { m_SensitivityXMIN = tempX; } } if(YMIN < tempY && tempY < YMAX) { if(tempY > m_SensitivityYMAX) { m_SensitivityYMAX = tempY; } else if(tempY < m_SensitivityYMIN) { m_SensitivityYMIN = tempY; } } return true; } bool mitk::WiiMoteVtkCameraController::FinishCalibration(mitk::Action *a, const mitk::StateEvent *e) { // checks if one of the properties was not set at all during the calibration // should that happen, the computation will not be executed if( m_SensitivityXMAX != XMIN && m_SensitivityXMIN != XMAX && m_SensitivityYMAX != YMIN && m_SensitivityYMIN != YMAX ) { // computation of the sensitivity out of the calibration data m_SensitivityX = XMAX / (m_SensitivityXMAX - m_SensitivityXMIN); m_SensitivityX *= CALIBRATIONFACTORX; m_SensitivityY = YMAX / (m_SensitivityYMAX - m_SensitivityYMIN); m_SensitivityY *= CALIBRATIONFACTORY; this->m_Calibrated = true; } if(!m_Calibrated) { MITK_INFO << "Calibration was unsuccesful - " << "please repeat the process and move in all directions!"; } else { MITK_INFO << "Ending calibration - other wiimote functionality reactivated."; } return m_Calibrated; } diff --git a/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.h b/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.h index 3af5f4bbef..ce0404df9b 100644 --- a/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.h +++ b/Modules/InputDevices/WiiMote/mitkWiiMoteVtkCameraController.h @@ -1,61 +1,76 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITK_WIIMOTEVTKCAMERACONTROLLER_H #define MITK_WIIMOTEVTKCAMERACONTROLLER_H // export #include "mitkWiiMoteExports.h" // mitk #include "mitkCameraController.h" #include "mitkAction.h" #include "mitkEvent.h" #include "mitkBaseRenderer.h" #include "mitkWiiMoteIREvent.h" #include "mitkWiiMoteCalibrationEvent.h" namespace mitk { class mitkWiiMote_EXPORT WiiMoteVtkCameraController : public CameraController { public: //SmartPointer Macros mitkClassMacro(WiiMoteVtkCameraController, CameraController); itkNewMacro(Self); protected: WiiMoteVtkCameraController(); ~WiiMoteVtkCameraController(); private: // head tracking bool OnWiiMoteInput(mitk::Action* a, const mitk::StateEvent* e); bool ResetView(mitk::Action* a, const mitk::StateEvent* e); bool m_ClippingRangeIsSet; double m_CurrentElevationAngle; double m_CurrentAzimuthAngle; // calibration bool m_Calibrated; double m_SensitivityXMAX; double m_SensitivityXMIN; double m_SensitivityYMAX; double m_SensitivityYMIN; double m_SensitivityX; double m_SensitivityY; bool InitCalibration(mitk::Action* a, const mitk::StateEvent* e); bool Calibration(mitk::Action* a, const mitk::StateEvent* e); bool FinishCalibration(mitk::Action* a, const mitk::StateEvent* e); // slice scrolling mitk::BaseRenderer::Pointer m_TransversalBR; double m_InitialScrollValue; int m_UpdateFrequency; }; // end class } // end namespace mitk #endif // MITK_WIIMOTEVTKCAMERACONTROLLER_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/wiiyourself/wiimote.cpp b/Modules/InputDevices/WiiMote/wiiyourself/wiimote.cpp index 5339313b29..37f5aa49c1 100644 --- a/Modules/InputDevices/WiiMote/wiiyourself/wiimote.cpp +++ b/Modules/InputDevices/WiiMote/wiiyourself/wiimote.cpp @@ -1,2817 +1,2832 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ // _______________________________________________________________________________ // // - WiiYourself! - native C++ Wiimote library v1.15 // (c) gl.tter 2007-10 - http://gl.tter.org // // see License.txt for conditions of use. see History.txt for change log. // _______________________________________________________________________________ // // wiimote.cpp (tab = 4 spaces) // VC-specifics: #ifdef _MSC_VER // disable warning "C++ exception handler used, but unwind semantics are not enabled." // in (I don't use it - or just enable C++ exceptions) # pragma warning(disable: 4530) // auto-link with the necessary libs # pragma comment(lib, "setupapi.lib") # pragma comment(lib, "hid.lib") // for HID API (from DDK) # pragma comment(lib, "winmm.lib") // for timeGetTime() #endif // _MSC_VER #include "wiimote.h" #include extern "C" { # ifdef __MINGW32__ # include // from WinDDK # else # include # endif } #include // for _stat #include // " #include // for _beginthreadex() #ifdef __BORLANDC__ # include // for orientation #else # include // " #endif #include // for WAVEFORMATEXTENSIBLE #include // for timeGetTime() // apparently not defined in some compilers: #ifndef min # define min(a,b) (((a) < (b)) ? (a) : (b)) #endif // ------------------------------------------------------------------------------------ // helpers // ------------------------------------------------------------------------------------ template inline T sign (const T& val) { return (val<0)? T(-1) : T(1); } template inline T square(const T& val) { return val*val; } #define ARRAY_ENTRIES(array) (sizeof(array)/sizeof(array[0])) // ------------------------------------------------------------------------------------ // Tracing & Debugging // ------------------------------------------------------------------------------------ #define PREFIX _T("WiiYourself! : ") // comment these to auto-strip their code from the library: // (they currently use OutputDebugString() via _TRACE() - change to suit) #if (_MSC_VER >= 1400) // VC 2005+ (earlier versions don't support variable args) # define TRACE(fmt, ...) _TRACE(PREFIX fmt _T("\n"), __VA_ARGS__) # define WARN(fmt, ...) _TRACE(PREFIX _T("* ") fmt _T(" *") _T("\n"), __VA_ARGS__) #elif defined(__MINGW32__) # define TRACE(fmt, ...) _TRACE(PREFIX fmt _T("\n") , ##__VA_ARGS__) # define WARN(fmt, ...) _TRACE(PREFIX _T("* ") fmt _T(" *") _T("\n") , ##__VA_ARGS__) #endif // uncomment any of these for deeper debugging: //#define DEEP_TRACE(fmt, ...) _TRACE(PREFIX _T("|") fmt _T("\n"), __VA_ARGS__) // VC 2005+ //#define DEEP_TRACE(fmt, ...) _TRACE(PREFIX _T("|") fmt _T("\n") , ##__VA_ARGS__) // mingw //#define BEEP_DEBUG_READS //#define BEEP_DEBUG_WRITES //#define BEEP_ON_ORIENTATION_ESTIMATE //#define BEEP_ON_PERIODIC_STATUSREFRESH // internals: auto-strip code from the macros if they weren't defined #ifndef TRACE # define TRACE #endif #ifndef DEEP_TRACE # define DEEP_TRACE #endif #ifndef WARN # define WARN #endif // ------------------------------------------------------------------------------------ static void _cdecl _TRACE (const TCHAR* fmt, ...) { static TCHAR buffer[256]; if (!fmt) return; va_list argptr; va_start (argptr, fmt); #if (_MSC_VER >= 1400) // VC 2005+ _vsntprintf_s(buffer, ARRAY_ENTRIES(buffer), _TRUNCATE, fmt, argptr); #else _vsntprintf (buffer, ARRAY_ENTRIES(buffer), fmt, argptr); #endif va_end (argptr); OutputDebugString(buffer); } // ------------------------------------------------------------------------------------ // wiimote // ------------------------------------------------------------------------------------ // class statics HMODULE wiimote::HidDLL = NULL; unsigned wiimote::_TotalCreated = 0; unsigned wiimote::_TotalConnected = 0; hidwrite_ptr wiimote::_HidD_SetOutputReport = NULL; // (keep in sync with 'speaker_freq'): const unsigned wiimote::FreqLookup [TOTAL_FREQUENCIES] = { 0, 4200, 3920, 3640, 3360, 3130, 2940, 2760, 2610, 2470 }; const TCHAR* wiimote::ButtonNameFromBit [TOTAL_BUTTON_BITS] = { _T("Left") , _T("Right"), _T("Down"), _T("Up"), _T("Plus") , _T("??") , _T("??") , _T("??") , _T("Two") , _T("One") , _T("B") , _T("A") , _T("Minus"), _T("??") , _T("??") , _T("Home") }; const TCHAR* wiimote::ClassicButtonNameFromBit [TOTAL_BUTTON_BITS] = { _T("??") , _T("TrigR") , _T("Plus") , _T("Home"), _T("Minus"), _T("TrigL") , _T("Down") , _T("Right") , _T("Up") , _T("Left") , _T("ZR") , _T("X") , _T("A") , _T("Y") , _T("B") , _T("ZL") }; // ------------------------------------------------------------------------------------ wiimote::wiimote () : DataRead (CreateEvent(NULL, FALSE, FALSE, NULL)), Handle (INVALID_HANDLE_VALUE), ReportType (IN_BUTTONS), bStatusReceived (false), // for output method detection bConnectInProgress (true ), bInitInProgress (false), bEnablingMotionPlus (false), bConnectionLost (false), // set if write fails after connection bMotionPlusDetected (false), bMotionPlusEnabled (false), bMotionPlusExtension (false), bCalibrateAtRest (false), bUseHIDwrite (false), // if OS supports it ChangedCallback (NULL), CallbackTriggerFlags (CHANGED_ALL), InternalChanged (NO_CHANGE), CurrentSample (NULL), HIDwriteThread (NULL), ReadParseThread (NULL), SampleThread (NULL), AsyncRumbleThread (NULL), AsyncRumbleTimeout (0), UniqueID (0) // not _guaranteed_ unique, see comments in header #ifdef ID2_FROM_DEVICEPATH // (see comments in header) // UniqueID2 (0) #endif { _ASSERT(DataRead != INVALID_HANDLE_VALUE); // if this is the first wiimote object, detect & enable HID write support if(++_TotalCreated == 1) { HidDLL = LoadLibrary(_T("hid.dll")); _ASSERT(HidDLL); if(!HidDLL) WARN(_T("Couldn't load hid.dll - shouldn't happen!")); else{ _HidD_SetOutputReport = (hidwrite_ptr) GetProcAddress(HidDLL, "HidD_SetOutputReport"); if(_HidD_SetOutputReport) TRACE(_T("OS supports HID writes.")); else TRACE(_T("OS doesn't support HID writes.")); } } // clear our public and private state data completely (including deadzones) Clear (true); Internal.Clear(true); // and the state recording vars memset(&Recording, 0, sizeof(Recording)); // for overlapped IO (Read/WriteFile) memset(&Overlapped, 0, sizeof(Overlapped)); Overlapped.hEvent = DataRead; Overlapped.Offset = Overlapped.OffsetHigh = 0; // for async HID output method InitializeCriticalSection(&HIDwriteQueueLock); // for polling InitializeCriticalSection(&StateLock); // request millisecond timer accuracy timeBeginPeriod(1); } // ------------------------------------------------------------------------------------ wiimote::~wiimote () { Disconnect(); // events & critical sections are kept open for the lifetime of the object, // so tidy them up here: if(DataRead != INVALID_HANDLE_VALUE) CloseHandle(DataRead); DeleteCriticalSection(&HIDwriteQueueLock); DeleteCriticalSection(&StateLock); // tidy up timer accuracy request timeEndPeriod(1); // release HID DLL (for dynamic HID write method) if((--_TotalCreated == 0) && HidDLL) { FreeLibrary(HidDLL); HidDLL = NULL; _HidD_SetOutputReport = NULL; } } // ------------------------------------------------------------------------------------ bool wiimote::Connect (unsigned wiimote_index, bool force_hidwrites) { if(wiimote_index == FIRST_AVAILABLE) TRACE(_T("Connecting first available Wiimote:")); else TRACE(_T("Connecting Wiimote %u:"), wiimote_index); // auto-disconnect if user is being naughty if(IsConnected()) Disconnect(); // get the GUID of the HID class GUID guid; HidD_GetHidGuid(&guid); // get a handle to all devices that are part of the HID class // Brian: Fun fact: DIGCF_PRESENT worked on my machine just fine. I reinstalled // Vista, and now it no longer finds the Wiimote with that parameter enabled... HDEVINFO dev_info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);// | DIGCF_PRESENT); if(!dev_info) { WARN(_T("couldn't get device info")); return false; } // enumerate the devices SP_DEVICE_INTERFACE_DATA didata; didata.cbSize = sizeof(didata); unsigned index = 0; unsigned wiimotes_found = 0; while(SetupDiEnumDeviceInterfaces(dev_info, NULL, &guid, index, &didata)) { // get the buffer size for this device detail instance DWORD req_size = 0; SetupDiGetDeviceInterfaceDetail(dev_info, &didata, NULL, 0, &req_size, NULL); // (bizarre way of doing it) create a buffer large enough to hold the // fixed-size detail struct components, and the variable string size SP_DEVICE_INTERFACE_DETAIL_DATA *didetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*) new BYTE[req_size]; _ASSERT(didetail); didetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // now actually get the detail struct if(!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, didetail, req_size, &req_size, NULL)) { WARN(_T("couldn't get devinterface info for %u"), index); break; } // open a shared handle to the device to query it (this will succeed even // if the wiimote is already Connect()'ed) DEEP_TRACE(_T(".. querying device %s"), didetail->DevicePath); Handle = CreateFile(didetail->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(Handle == INVALID_HANDLE_VALUE) { DEEP_TRACE(_T(".... failed with err %x (probably harmless)."), GetLastError()); goto skip; } // get the device attributes HIDD_ATTRIBUTES attrib; attrib.Size = sizeof(attrib); if(HidD_GetAttributes(Handle, &attrib)) { // is this a wiimote? if((attrib.VendorID != VID) || (attrib.ProductID != PID)) goto skip; // yes, but is it the one we're interested in? ++wiimotes_found; if((wiimote_index != FIRST_AVAILABLE) && (wiimote_index != wiimotes_found)) goto skip; // the wiimote is installed, but it may not be currently paired: if(wiimote_index == FIRST_AVAILABLE) TRACE(_T(".. opening Wiimote %u:"), wiimotes_found); else TRACE(_T(".. opening:")); // re-open the handle, but this time we don't allow write sharing // (that way subsequent calls can still _discover_ wiimotes above, but // will correctly fail here if they're already connected) CloseHandle(Handle); // note this also means that if another application has already opened // the device, the library can no longer connect it (this may happen // with software that enumerates all joysticks in the system, because // even though the wiimote is not a standard joystick (and can't // be read as such), it unfortunately announces itself to the OS // as one. The SDL library was known to do grab wiimotes like this. // If you cannot stop the application from doing it, you may change the // call below to open the device in full shared mode - but then the // library can no longer detect if you've already connected a device // and will allow you to connect it twice! So be careful ... Handle = CreateFile(didetail->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(Handle == INVALID_HANDLE_VALUE) { TRACE(_T(".... failed with err %x"), GetLastError()); goto skip; } // clear the wiimote state & buffers Clear (false); // preserves existing deadzones Internal.Clear(false); // " InternalChanged = NO_CHANGE; memset(ReadBuff , 0, sizeof(ReadBuff)); bConnectionLost = false; bConnectInProgress = true; // don't parse extensions or request regular // updates until complete // enable async reading BeginAsyncRead(); // autodetect which write method the Bluetooth stack supports, // by requesting the wiimote status report: if(force_hidwrites && !_HidD_SetOutputReport) { TRACE(_T(".. can't force HID writes (not supported)")); force_hidwrites = false; } if(force_hidwrites) TRACE(_T(".. (HID writes forced)")); else{ // - try WriteFile() first as it's the most efficient (it uses // harware interrupts where possible and is async-capable): bUseHIDwrite = false; RequestStatusReport(); // and wait for the report to arrive: DWORD last_time = timeGetTime(); while(!bStatusReceived && ((timeGetTime()-last_time) < 500)) Sleep(10); TRACE(_T(".. WriteFile() %s."), bStatusReceived? _T("succeeded") : _T("failed")); } // try HID write method (if supported) if(!bStatusReceived && _HidD_SetOutputReport) { bUseHIDwrite = true; RequestStatusReport(); // wait for the report to arrive: DWORD last_time = timeGetTime(); while(!bStatusReceived && ((timeGetTime()-last_time) < 500)) Sleep(10); // did we get it? TRACE(_T(".. HID write %s."), bStatusReceived? _T("succeeded") : _T("failed")); } // still failed? if(!bStatusReceived) { WARN(_T("output failed - wiimote is not connected (or confused).")); Disconnect(); goto skip; } //Sleep(500); // reset it Reset(); // read the wiimote calibration info ReadCalibration(); // allow the result(s) to come in (so that the caller can immediately test // MotionPlusConnected() Sleep(300); // note, don't need it on my system, better to be safe though // connected succesfully: _TotalConnected++; // use the first incomding analogue sensor values as the 'at rest' // offsets (only supports the Balance Board currently) bCalibrateAtRest = true; // refresh the public state from the internal one (so that everything // is available straight away RefreshState(); // attempt to construct a unique hardware ID from the calibration // data bytes (this is obviously not guaranteed to be unique across // all devices, but may work fairly well in practice... ?) memcpy(&UniqueID, &CalibrationInfo, sizeof(CalibrationInfo)); _ASSERT(UniqueID != 0); // if this fires, the calibration data didn't // arrive - this shouldn't happen #ifdef ID2_FROM_DEVICEPATH // (see comments in header) // create a 2nd alternative id by simply adding all the characters // in the device path to create a single number UniqueID2 = 0; for(unsigned index=0; index<_tcslen(didetail->DevicePath); index++) UniqueID2 += didetail->DevicePath[index]; #endif // and show when we want to trigger the next periodic status request // (for battery level and connection loss detection) NextStatusTime = timeGetTime() + REQUEST_STATUS_EVERY_MS; NextMPlusDetectTime = timeGetTime() + DETECT_MPLUS_EVERY_MS; MPlusDetectCount = DETECT_MPLUS_COUNT; // tidy up delete[] (BYTE*)didetail; break; } skip: // tidy up delete[] (BYTE*)didetail; if(Handle != INVALID_HANDLE_VALUE) { CloseHandle(Handle); Handle = INVALID_HANDLE_VALUE; } // if this was the specified wiimote index, abort if((wiimote_index != FIRST_AVAILABLE) && (wiimote_index == (wiimotes_found-1))) break; index++; } // clean up our list SetupDiDestroyDeviceInfoList(dev_info); bConnectInProgress = false; if(IsConnected()) { TRACE(_T(".. connected!")); // notify the callbacks (if requested to do so) if(CallbackTriggerFlags & CONNECTED) { ChangedNotifier(CONNECTED, Internal); if(ChangedCallback) ChangedCallback(*this, CONNECTED, Internal); } return true; } TRACE(_T(".. connection failed.")); return false; } // ------------------------------------------------------------------------------------ void wiimote::CalibrateAtRest () { _ASSERT(IsConnected()); if(!IsConnected()) return; // the app calls this to remove 'at rest' offsets from the analogue sensor // values (currently only works for the Balance Board): if(IsBalanceBoard()) { TRACE(_T(".. removing 'at rest' BBoard offsets.")); Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg; RefreshState(); } } // ------------------------------------------------------------------------------------ void wiimote::Disconnect () { if(Handle == INVALID_HANDLE_VALUE) return; TRACE(_T("Disconnect().")); if(IsConnected()) { _ASSERT(_TotalConnected > 0); // sanity _TotalConnected--; if(!bConnectionLost) Reset(); } CloseHandle(Handle); Handle = INVALID_HANDLE_VALUE; UniqueID = 0; #ifdef ID2_FROM_DEVICEPATH // (see comments in header) UniqueID2 = 0; #endif // close the read thread if(ReadParseThread) { // unblock it so it can realise we're closing and exit straight away SetEvent(DataRead); WaitForSingleObject(ReadParseThread, 3000); CloseHandle(ReadParseThread); ReadParseThread = NULL; } // close the rumble thread if(AsyncRumbleThread) { WaitForSingleObject(AsyncRumbleThread, 3000); CloseHandle(AsyncRumbleThread); AsyncRumbleThread = NULL; AsyncRumbleTimeout = 0; } // and the sample streaming thread if(SampleThread) { WaitForSingleObject(SampleThread, 3000); CloseHandle(SampleThread); SampleThread = NULL; } #ifndef USE_DYNAMIC_HIDQUEUE HID.Deallocate(); #endif bStatusReceived = false; // and clear the state Clear (false); // (preserves deadzones) Internal.Clear(false); // " InternalChanged = NO_CHANGE; } // ------------------------------------------------------------------------------------ void wiimote::Reset () { TRACE(_T("Resetting wiimote.")); if(bMotionPlusEnabled) DisableMotionPlus(); // stop updates (by setting report type to non-continuous, buttons-only) if(IsBalanceBoard()) SetReportType(IN_BUTTONS_BALANCE_BOARD, false); else SetReportType(IN_BUTTONS, false); SetRumble (false); SetLEDs (0x00); // MuteSpeaker (true); EnableSpeaker(false); Sleep(150); // avoids loosing the extension calibration data on Connect() } // ------------------------------------------------------------------------------------ unsigned __stdcall wiimote::ReadParseThreadfunc (void* param) { // this thread waits for the async ReadFile() to deliver data & parses it. // it also requests periodic status updates, deals with connection loss // and ends state recordings with a specific duration: _ASSERT(param); wiimote &remote = *(wiimote*)param; OVERLAPPED &overlapped = remote.Overlapped; unsigned exit_code = 0; // (success) while(1) { // wait until the overlapped read completes, or the timeout is reached: DWORD wait = WaitForSingleObject(overlapped.hEvent, 500); // before we deal with the result, let's do some housekeeping: // if we were recently Disconect()ed, exit now if(remote.Handle == INVALID_HANDLE_VALUE) { DEEP_TRACE(_T("read thread: wiimote was disconnected")); break; } // ditto if the connection was lost (eg. through a failed write) if(remote.bConnectionLost) { connection_lost: TRACE(_T("read thread: connection to wiimote was lost")); remote.Disconnect(); remote.InternalChanged = (state_change_flags) (remote.InternalChanged | CONNECTION_LOST); // report via the callback (if any) if(remote.CallbackTriggerFlags & CONNECTION_LOST) { remote.ChangedNotifier(CONNECTION_LOST, remote.Internal); if(remote.ChangedCallback) remote.ChangedCallback(remote, CONNECTION_LOST, remote.Internal); } break; } DWORD time = timeGetTime(); // periodic events (but not if we're streaming audio, // we don't want to cause a glitch) if(remote.IsConnected() && !remote.bInitInProgress && !remote.IsPlayingAudio()) { // status request due? if(time > remote.NextStatusTime) { #ifdef BEEP_ON_PERIODIC_STATUSREFRESH Beep(2000,50); #endif remote.RequestStatusReport(); // and schedule the next one remote.NextStatusTime = time + REQUEST_STATUS_EVERY_MS; } // motion plus detection due? if(!remote.IsBalanceBoard() && // !remote.bConnectInProgress && !remote.bMotionPlusExtension && (remote.Internal.ExtensionType != MOTION_PLUS) && (remote.Internal.ExtensionType != PARTIALLY_INSERTED) && (time > remote.NextMPlusDetectTime)) { remote.DetectMotionPlusExtensionAsync(); // we try several times in quick succession before the next // delay: if(--remote.MPlusDetectCount == 0) { remote.NextMPlusDetectTime = time + DETECT_MPLUS_EVERY_MS; remote.MPlusDetectCount = DETECT_MPLUS_COUNT; #ifdef _DEBUG TRACE(_T("--")); #endif } } } // if we're state recording and have reached the specified duration, stop if(remote.Recording.bEnabled && (remote.Recording.EndTimeMS != UNTIL_STOP) && (time >= remote.Recording.EndTimeMS)) remote.Recording.bEnabled = false; // now handle the wait result: // did the wait time out? if(wait == WAIT_TIMEOUT) { DEEP_TRACE(_T("read thread: timed out")); continue; // wait again } // did an error occurr? if(wait != WAIT_OBJECT_0) { DEEP_TRACE(_T("read thread: error waiting!")); remote.bConnectionLost = true; // deal with it straight away to avoid a longer delay goto connection_lost; } // data was received: #ifdef BEEP_DEBUG_READS Beep(500,1); #endif DWORD read = 0; // get the data read result GetOverlappedResult(remote.Handle, &overlapped, &read, TRUE); // if we read data, parse it if(read) { DEEP_TRACE(_T("read thread: parsing data")); remote.OnReadData(read); } else DEEP_TRACE(_T("read thread: didn't get any data??")); } TRACE(_T("(ending read thread)")); #ifdef BEEP_DEBUG_READS if(exit_code != 0) Beep(200,1000); #endif return exit_code; } // ------------------------------------------------------------------------------------ bool wiimote::BeginAsyncRead () { // (this is also called before we're fully connected) if(Handle == INVALID_HANDLE_VALUE) return false; DEEP_TRACE(_T(".. starting async read")); #ifdef BEEP_DEBUG_READS Beep(1000,1); #endif DWORD read; if (!ReadFile(Handle, ReadBuff, REPORT_LENGTH, &read, &Overlapped)) { DWORD err = GetLastError(); if(err != ERROR_IO_PENDING) { DEEP_TRACE(_T(".... ** ReadFile() failed! **")); return false; } } // launch the completion wait/callback thread if(!ReadParseThread) { ReadParseThread = (HANDLE)_beginthreadex(NULL, 0, ReadParseThreadfunc, this, 0, NULL); DEEP_TRACE(_T(".... creating read thread")); _ASSERT(ReadParseThread); if(!ReadParseThread) return false; SetThreadPriority(ReadParseThread, WORKER_THREAD_PRIORITY); } // if ReadFile completed while we called, signal the thread to proceed if(read) { DEEP_TRACE(_T(".... got data right away")); SetEvent(DataRead); } return true; } // ------------------------------------------------------------------------------------ void wiimote::OnReadData (DWORD bytes_read) { _ASSERT(bytes_read == REPORT_LENGTH); // copy our input buffer BYTE buff [REPORT_LENGTH]; memcpy(buff, ReadBuff, bytes_read); // start reading again BeginAsyncRead(); // parse it ParseInput(buff); } // ------------------------------------------------------------------------------------ void wiimote::SetReportType (input_report type, bool continuous) { _ASSERT(IsConnected()); if(!IsConnected()) return; // the balance board only uses one type of report _ASSERT(!IsBalanceBoard() || type == IN_BUTTONS_BALANCE_BOARD); if(IsBalanceBoard() && (type != IN_BUTTONS_BALANCE_BOARD)) return; #ifdef TRACE #define TYPE2NAME(_type) (type==_type)? _T(#_type) const TCHAR* name = TYPE2NAME(IN_BUTTONS) : TYPE2NAME(IN_BUTTONS_ACCEL_IR) : TYPE2NAME(IN_BUTTONS_ACCEL_EXT) : TYPE2NAME(IN_BUTTONS_ACCEL_IR_EXT) : TYPE2NAME(IN_BUTTONS_BALANCE_BOARD) : _T("(unknown??)"); TRACE(_T("ReportType: %s (%s)"), name, (continuous? _T("continuous") : _T("non-continuous"))); #endif ReportType = type; switch(type) { case IN_BUTTONS_ACCEL_IR: EnableIR(wiimote_state::ir::EXTENDED); break; case IN_BUTTONS_ACCEL_IR_EXT: EnableIR(wiimote_state::ir::BASIC); break; default: DisableIR(); break; } BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_TYPE; buff[1] = (continuous ? 0x04 : 0x00) | GetRumbleBit(); buff[2] = (BYTE)type; WriteReport(buff); // Sleep(15); } // ------------------------------------------------------------------------------------ void wiimote::SetLEDs (BYTE led_bits) { _ASSERT(IsConnected()); if(!IsConnected() || bInitInProgress) return; _ASSERT(led_bits <= 0x0f); led_bits &= 0xf; BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_LEDs; buff[1] = (led_bits<<4) | GetRumbleBit(); WriteReport(buff); Internal.LED.Bits = led_bits; } // ------------------------------------------------------------------------------------ void wiimote::SetRumble (bool on) { _ASSERT(IsConnected()); if(!IsConnected()) return; if(Internal.bRumble == on) return; Internal.bRumble = on; // if we're streaming audio, we don't need to send a report (sending it makes // the audio glitch, and the rumble bit is sent with every report anyway) if(IsPlayingAudio()) return; BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_STATUS; buff[1] = on? 0x01 : 0x00; WriteReport(buff); } // ------------------------------------------------------------------------------------ unsigned __stdcall wiimote::AsyncRumbleThreadfunc (void* param) { // auto-disables rumble after x milliseconds: _ASSERT(param); wiimote &remote = *(wiimote*)param; while(remote.IsConnected()) { if(remote.AsyncRumbleTimeout) { DWORD current_time = timeGetTime(); if(current_time >= remote.AsyncRumbleTimeout) { if(remote.Internal.bRumble) remote.SetRumble(false); remote.AsyncRumbleTimeout = 0; } Sleep(1); } else Sleep(4); } return 0; } // ------------------------------------------------------------------------------------ void wiimote::RumbleForAsync (unsigned milliseconds) { // rumble for a fixed amount of time _ASSERT(IsConnected()); if(!IsConnected()) return; SetRumble(true); // show how long thread should wait to disable rumble again // (it it's currently rumbling it will just extend the time) AsyncRumbleTimeout = timeGetTime() + milliseconds; // create the thread? if(AsyncRumbleThread) return; AsyncRumbleThread = (HANDLE)_beginthreadex(NULL, 0, AsyncRumbleThreadfunc, this, 0, NULL); _ASSERT(AsyncRumbleThread); if(!AsyncRumbleThread) { WARN(_T("couldn't create rumble thread!")); return; } SetThreadPriority(AsyncRumbleThread, WORKER_THREAD_PRIORITY); } // ------------------------------------------------------------------------------------ void wiimote::RequestStatusReport () { // (this can be called before we're fully connected) _ASSERT(Handle != INVALID_HANDLE_VALUE); if(Handle == INVALID_HANDLE_VALUE) return; BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_STATUS; buff[1] = GetRumbleBit(); WriteReport(buff); } // ------------------------------------------------------------------------------------ bool wiimote::ReadAddress (int address, short size) { // asynchronous BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_READMEMORY; buff[1] = (BYTE)(((address & 0xff000000) >> 24) | GetRumbleBit()); buff[2] = (BYTE)( (address & 0x00ff0000) >> 16); buff[3] = (BYTE)( (address & 0x0000ff00) >> 8); buff[4] = (BYTE)( (address & 0x000000ff)); buff[5] = (BYTE)( (size & 0xff00 ) >> 8); buff[6] = (BYTE)( (size & 0xff)); return WriteReport(buff); } // ------------------------------------------------------------------------------------ void wiimote::WriteData (int address, BYTE size, const BYTE* buff) { // asynchronous BYTE write [REPORT_LENGTH] = {0}; write[0] = OUT_WRITEMEMORY; write[1] = (BYTE)(((address & 0xff000000) >> 24) | GetRumbleBit()); write[2] = (BYTE)( (address & 0x00ff0000) >> 16); write[3] = (BYTE)( (address & 0x0000ff00) >> 8); write[4] = (BYTE)( (address & 0x000000ff)); write[5] = size; memcpy(write+6, buff, size); WriteReport(write); } // ------------------------------------------------------------------------------------ int wiimote::ParseInput (BYTE* buff) { int changed = 0; // lock our internal state (so RefreshState() is blocked until we're done EnterCriticalSection(&StateLock); switch(buff[0]) { case IN_BUTTONS: DEEP_TRACE(_T(".. parsing buttons.")); changed |= ParseButtons(buff); break; case IN_BUTTONS_ACCEL: DEEP_TRACE(_T(".. parsing buttons/accel.")); changed |= ParseButtons(buff); if(!IsBalanceBoard()) changed |= ParseAccel(buff); break; case IN_BUTTONS_ACCEL_EXT: DEEP_TRACE(_T(".. parsing extenion/accel.")); changed |= ParseButtons(buff); changed |= ParseExtension(buff, 6); if(!IsBalanceBoard()) changed |= ParseAccel(buff); break; case IN_BUTTONS_ACCEL_IR: DEEP_TRACE(_T(".. parsing ir/accel.")); changed |= ParseButtons(buff); if(!IsBalanceBoard()) { changed |= ParseAccel(buff); changed |= ParseIR(buff); } break; case IN_BUTTONS_ACCEL_IR_EXT: DEEP_TRACE(_T(".. parsing ir/extenion/accel.")); changed |= ParseButtons(buff); changed |= ParseExtension(buff, 16); if(!IsBalanceBoard()) { changed |= ParseAccel(buff); changed |= ParseIR (buff); } break; case IN_BUTTONS_BALANCE_BOARD: DEEP_TRACE(_T(".. parsing buttson/balance.")); changed |= ParseButtons(buff); changed |= ParseExtension(buff, 3); break; case IN_READADDRESS: DEEP_TRACE(_T(".. parsing read address.")); changed |= ParseButtons (buff); changed |= ParseReadAddress(buff); break; case IN_STATUS: DEEP_TRACE(_T(".. parsing status.")); changed |= ParseStatus(buff); // show that we received the status report (used for output method // detection during Connect()) bStatusReceived = true; break; default: DEEP_TRACE(_T(".. ** unknown input ** (happens).")); ///_ASSERT(0); //Debug.WriteLine("Unknown report type: " + type.ToString()); LeaveCriticalSection(&StateLock); return false; } // if we're recording and some state we care about has changed, insert it into // the state history if(Recording.bEnabled && (changed & Recording.TriggerFlags)) { DEEP_TRACE(_T(".. adding state to history")); state_event event; event.time_ms = timeGetTime(); event.state = *(wiimote_state*)this; Recording.StateHistory->push_back(event); } // for polling: show which state has changed since the last RefreshState() InternalChanged = (state_change_flags)(InternalChanged | changed); LeaveCriticalSection(&StateLock); // callbacks: call it (if set & state the app is interested in has changed) if(changed & CallbackTriggerFlags) { DEEP_TRACE(_T(".. calling state change callback")); ChangedNotifier((state_change_flags)changed, Internal); if(ChangedCallback) ChangedCallback(*this, (state_change_flags)changed, Internal); } DEEP_TRACE(_T(".. parse complete.")); return true; } // ------------------------------------------------------------------------------------ state_change_flags wiimote::RefreshState () { // nothing changed since the last call? if(InternalChanged == NO_CHANGE) return NO_CHANGE; // copy the internal state to our public data members: // synchronise the interal state with the read/parse thread (we don't want // values changing during the copy) EnterCriticalSection(&StateLock); // remember which state changed since the last call state_change_flags changed = InternalChanged; // preserve the application-set deadzones (if any) joystick::deadzone nunchuk_deadzone = Nunchuk.Joystick.DeadZone; joystick::deadzone classic_joyl_deadzone = ClassicController.JoystickL.DeadZone; joystick::deadzone classic_joyr_deadzone = ClassicController.JoystickR.DeadZone; // copy the internal state to the public one *(wiimote_state*)this = Internal; InternalChanged = NO_CHANGE; // restore the application-set deadzones Nunchuk.Joystick.DeadZone = nunchuk_deadzone; ClassicController.JoystickL.DeadZone = classic_joyl_deadzone; ClassicController.JoystickR.DeadZone = classic_joyr_deadzone; LeaveCriticalSection(&StateLock); return changed; } // ------------------------------------------------------------------------------------ void wiimote::DetectMotionPlusExtensionAsync () { #ifdef _DEBUG TRACE(_T("(looking for motion plus)")); #endif // show that we're expecting the result shortly MotionPlusDetectCount++; // MotionPLus reports at a different address than other extensions (until // activated, when it maps itself into the usual extension registers), so // try to detect it first: ReadAddress(REGISTER_MOTIONPLUS_DETECT, 6); } // ------------------------------------------------------------------------------------ bool wiimote::EnableMotionPlus () { _ASSERT(bMotionPlusDetected); if(!bMotionPlusDetected) return false; if(bMotionPlusEnabled) return true; TRACE(_T("Enabling Motion Plus:")); bMotionPlusExtension = false; bInitInProgress = true; bEnablingMotionPlus = true; // Initialize it: WriteData(REGISTER_MOTIONPLUS_INIT , 0x55); // Sleep(50); // Enable it (this maps it to the standard extension port): WriteData(REGISTER_MOTIONPLUS_ENABLE, 0x04); // Sleep(50); Sleep(500); return true; } // ------------------------------------------------------------------------------------ bool wiimote::DisableMotionPlus () { if(!bMotionPlusDetected || !bMotionPlusEnabled) return false; TRACE(_T("Disabling Motion Plus:")); // disable it (this makes standard extensions visible again) WriteData(REGISTER_EXTENSION_INIT1, 0x55); return true; } // ------------------------------------------------------------------------------------ void wiimote::InitializeExtension () { TRACE(_T("Initialising Extension.")); // wibrew.org: The new way to initialize the extension is by writing 0x55 to // 0x(4)A400F0, then writing 0x00 to 0x(4)A400FB. It works on all extensions, and // makes the extension type bytes unencrypted. This means that you no longer have // to decrypt the extension bytes using the transform listed above. bInitInProgress = true; _ASSERT(Internal.bExtension); // only initialize if it's not a MotionPlus if(!bEnablingMotionPlus) { WriteData (REGISTER_EXTENSION_INIT1, 0x55); WriteData (REGISTER_EXTENSION_INIT2, 0x00); } else bEnablingMotionPlus = false; ReadAddress(REGISTER_EXTENSION_TYPE , 6); } // ------------------------------------------------------------------------------------ int wiimote::ParseStatus (BYTE* buff) { // parse the buttons int changed = ParseButtons(buff); // get the battery level BYTE battery_raw = buff[6]; if(Internal.BatteryRaw != battery_raw) changed |= BATTERY_CHANGED; Internal.BatteryRaw = battery_raw; // it is estimated that ~200 is the maximum battery level Internal.BatteryPercent = battery_raw / 2; // there is also a flag that shows if the battery is nearly empty bool drained = buff[3] & 0x01; if(drained != bBatteryDrained) { bBatteryDrained = drained; if(drained) changed |= BATTERY_DRAINED; } // leds BYTE leds = buff[3] >> 4; if(leds != Internal.LED.Bits) changed |= LEDS_CHANGED; Internal.LED.Bits = leds; // don't handle extensions until a connection is complete // if(bConnectInProgress) // return changed; bool extension = ((buff[3] & 0x02) != 0); // TRACE(_T("(extension = %s)"), (extension? _T("TRUE") : _T("false"))); if(extension != Internal.bExtension) { if(!Internal.bExtension) { TRACE(_T("Extension connected:")); Internal.bExtension = true; InitializeExtension(); } else{ TRACE(_T("Extension disconnected.")); Internal.bExtension = false; Internal.ExtensionType = wiimote_state::NONE; bMotionPlusEnabled = false; bMotionPlusExtension = false; bMotionPlusDetected = false; bInitInProgress = false; bEnablingMotionPlus = false; changed |= EXTENSION_DISCONNECTED; // renable reports // SetReportType(ReportType); } } return changed; } // ------------------------------------------------------------------------------------ int wiimote::ParseButtons (BYTE* buff) { int changed = 0; // WORD bits = *(WORD*)(buff+1); WORD bits = *(WORD*)(buff+1) & Button.ALL; if(bits != Internal.Button.Bits) changed |= BUTTONS_CHANGED; Internal.Button.Bits = bits; return changed; } // ------------------------------------------------------------------------------------ bool wiimote::EstimateOrientationFrom (wiimote_state::acceleration &accel) { // Orientation estimate from acceleration data (shared between wiimote and nunchuk) // return true if the orientation was updated // assume the controller is stationary if the acceleration vector is near // 1g for several updates (this may not always be correct) float length_sq = square(accel.X) + square(accel.Y) + square(accel.Z); // TODO: as I'm comparing _squared_ length, I really need different // min/max epsilons... #define DOT(x1,y1,z1, x2,y2,z2) ((x1*x2) + (y1*y2) + (z1*z2)) static const float epsilon = 0.2f; if((length_sq >= (1.f-epsilon)) && (length_sq <= (1.f+epsilon))) { if(++WiimoteNearGUpdates < 2) return false; // wiimote seems to be stationary: normalize the current acceleration // (ie. the assumed gravity vector) float inv_len = 1.f / sqrt(length_sq); float x = accel.X * inv_len; float y = accel.Y * inv_len; float z = accel.Z * inv_len; // copy the values accel.Orientation.X = x; accel.Orientation.Y = y; accel.Orientation.Z = z; // and extract pitch & roll from them: // (may not be optimal) float pitch = -asin(y) * 57.2957795f; // float roll = asin(x) * 57.2957795f; float roll = atan2(x,z) * 57.2957795f; if(z < 0) { pitch = (y < 0)? 180 - pitch : -180 - pitch; roll = (x < 0)? -180 - roll : 180 - roll; } accel.Orientation.Pitch = pitch; accel.Orientation.Roll = roll; // show that we just updated orientation accel.Orientation.UpdateAge = 0; #ifdef BEEP_ON_ORIENTATION_ESTIMATE Beep(2000, 1); #endif return true; // updated } // not updated this time: WiimoteNearGUpdates = 0; // age the last orientation update accel.Orientation.UpdateAge++; return false; } // ------------------------------------------------------------------------------------ void wiimote::ApplyJoystickDeadZones (wiimote_state::joystick &joy) { // apply the deadzones to each axis (if set) if((joy.DeadZone.X > 0.f) && (joy.DeadZone.X <= 1.f)) { if(fabs(joy.X) <= joy.DeadZone.X) joy.X = 0; else{ joy.X -= joy.DeadZone.X * sign(joy.X); joy.X /= 1.f - joy.DeadZone.X; } } if((joy.DeadZone.Y > 0.f) && (joy.DeadZone.Y <= 1.f)) { if(fabs(joy.Y) <= joy.DeadZone.Y) joy.Y = 0; else{ joy.Y -= joy.DeadZone.Y * sign(joy.Y); joy.Y /= 1.f - joy.DeadZone.Y; } } } // ------------------------------------------------------------------------------------ int wiimote::ParseAccel (BYTE* buff) { int changed = 0; BYTE raw_x = buff[3]; BYTE raw_y = buff[4]; BYTE raw_z = buff[5]; BYTE raw_x_LSB = (buff[1] & 96) >> 5; BYTE raw_y_LSB = (buff[2] & 32) >> 5; BYTE raw_z_LSB = (buff[2] & 64) >> 6; if((raw_x != Internal.Acceleration.RawX) || (raw_x_LSB != Internal.Acceleration.RawXLSB) || (raw_y != Internal.Acceleration.RawY) || (raw_y_LSB != Internal.Acceleration.RawYLSB) || (raw_z != Internal.Acceleration.RawZ) || (raw_z_LSB != Internal.Acceleration.RawZLSB)) changed |= ACCEL_CHANGED; Internal.Acceleration.RawX = raw_x; Internal.Acceleration.RawY = raw_y; Internal.Acceleration.RawZ = raw_z; Internal.Acceleration.RawXLSB = raw_x_LSB; Internal.Acceleration.RawYLSB = raw_y_LSB; Internal.Acceleration.RawZLSB = raw_z_LSB; // avoid / 0.0 when calibration data hasn't arrived yet if(Internal.CalibrationInfo.X0) { Internal.Acceleration.X = ((float)Internal.Acceleration.RawX + (float)Internal.Acceleration.RawXLSB/4.0f - Internal.CalibrationInfo.X0) / ((float)Internal.CalibrationInfo.XG - Internal.CalibrationInfo.X0); Internal.Acceleration.Y = ((float)Internal.Acceleration.RawY + (float)Internal.Acceleration.RawYLSB/2.0f - Internal.CalibrationInfo.Y0) / ((float)Internal.CalibrationInfo.YG - Internal.CalibrationInfo.Y0); Internal.Acceleration.Z = ((float)Internal.Acceleration.RawZ + (float)Internal.Acceleration.RawZLSB/2.0f - Internal.CalibrationInfo.Z0) / ((float)Internal.CalibrationInfo.ZG - Internal.CalibrationInfo.Z0); } else{ Internal.Acceleration.X = Internal.Acceleration.Y = Internal.Acceleration.Z = 0.f; } // see if we can estimate the orientation from the current values if(EstimateOrientationFrom(Internal.Acceleration)) changed |= ORIENTATION_CHANGED; return changed; } // ------------------------------------------------------------------------------------ int wiimote::ParseIR (BYTE* buff) { if(Internal.IR.Mode == wiimote_state::ir::OFF) return NO_CHANGE; // avoid garbage values when the MotionPlus is enabled, but the app is // still using the extended IR report type if(bMotionPlusEnabled && (Internal.IR.Mode == wiimote_state::ir::EXTENDED)) return NO_CHANGE; // take a copy of the existing IR state (so we can detect changes) wiimote_state::ir prev_ir = Internal.IR; // only updates the other values if the dots are visible (so that the last // valid values stay unmodified) switch(Internal.IR.Mode) { case wiimote_state::ir::BASIC: // 2 dots are encoded in 5 bytes, so read 2 at a time for(unsigned step=0; step<2; step++) { ir::dot &dot0 = Internal.IR.Dot[step*2 ]; ir::dot &dot1 = Internal.IR.Dot[step*2+1]; const unsigned offs = 6 + (step*5); // 5 bytes for 2 dots dot0.bVisible = !(buff[offs ] == 0xff && buff[offs+1] == 0xff); dot1.bVisible = !(buff[offs+3] == 0xff && buff[offs+4] == 0xff); if(dot0.bVisible) { dot0.RawX = buff[offs ] | ((buff[offs+2] >> 4) & 0x03) << 8;; dot0.RawY = buff[offs+1] | ((buff[offs+2] >> 6) & 0x03) << 8;; dot0.X = 1.f - (dot0.RawX / (float)wiimote_state::ir::MAX_RAW_X); dot0.Y = (dot0.RawY / (float)wiimote_state::ir::MAX_RAW_Y); } if(dot1.bVisible) { dot1.RawX = buff[offs+3] | ((buff[offs+2] >> 0) & 0x03) << 8; dot1.RawY = buff[offs+4] | ((buff[offs+2] >> 2) & 0x03) << 8; dot1.X = 1.f - (dot1.RawX / (float)wiimote_state::ir::MAX_RAW_X); dot1.Y = (dot1.RawY / (float)wiimote_state::ir::MAX_RAW_Y); } } break; case wiimote_state::ir::EXTENDED: // each dot is encoded into 3 bytes for(unsigned index=0; index<4; index++) { ir::dot &dot = Internal.IR.Dot[index]; const unsigned offs = 6 + (index * 3); dot.bVisible = !(buff[offs ]==0xff && buff[offs+1]==0xff && buff[offs+2]==0xff); if(dot.bVisible) { dot.RawX = buff[offs ] | ((buff[offs+2] >> 4) & 0x03) << 8; dot.RawY = buff[offs+1] | ((buff[offs+2] >> 6) & 0x03) << 8; dot.X = 1.f - (dot.RawX / (float)wiimote_state::ir::MAX_RAW_X); dot.Y = (dot.RawY / (float)wiimote_state::ir::MAX_RAW_Y); dot.Size = buff[offs+2] & 0x0f; } } break; case wiimote_state::ir::FULL: _ASSERT(0); // not supported yet; break; } return memcmp(&prev_ir, &Internal.IR, sizeof(Internal.IR))? IR_CHANGED : 0; } // ------------------------------------------------------------------------------------ inline float wiimote::GetBalanceValue (short sensor, short min, short mid, short max) { if(max == mid || mid == min) return 0; float val = (sensor < mid)? 68.0f * ((float)(sensor - min) / (mid - min)) : 68.0f * ((float)(sensor - mid) / (max - mid)) + 68.0f; // divide by four (so that each sensor is correct) return val * 0.25f; } // ------------------------------------------------------------------------------------ int wiimote::ParseExtension (BYTE *buff, unsigned offset) { int changed = 0; switch(Internal.ExtensionType) { case wiimote_state::NUNCHUK: { // buttons bool c = (buff[offset+5] & 0x02) == 0; bool z = (buff[offset+5] & 0x01) == 0; if((c != Internal.Nunchuk.C) || (z != Internal.Nunchuk.Z)) changed |= NUNCHUK_BUTTONS_CHANGED; Internal.Nunchuk.C = c; Internal.Nunchuk.Z = z; // acceleration { wiimote_state::acceleration &accel = Internal.Nunchuk.Acceleration; BYTE raw_x = buff[offset+2]; BYTE raw_y = buff[offset+3]; BYTE raw_z = buff[offset+4]; if((raw_x != accel.RawX) || (raw_y != accel.RawY) || (raw_z != accel.RawZ)) changed |= NUNCHUK_ACCEL_CHANGED; accel.RawX = raw_x; accel.RawY = raw_y; accel.RawZ = raw_z; wiimote_state::nunchuk::calibration_info &calib = Internal.Nunchuk.CalibrationInfo; accel.X = ((float)raw_x - calib.X0) / ((float)calib.XG - calib.X0); accel.Y = ((float)raw_y - calib.Y0) / ((float)calib.YG - calib.Y0); accel.Z = ((float)raw_z - calib.Z0) / ((float)calib.ZG - calib.Z0); // try to extract orientation from the accel: if(EstimateOrientationFrom(accel)) changed |= NUNCHUK_ORIENTATION_CHANGED; } { // joystick: wiimote_state::joystick &joy = Internal.Nunchuk.Joystick; float raw_x = buff[offset+0]; float raw_y = buff[offset+1]; if((raw_x != joy.RawX) || (raw_y != joy.RawY)) changed |= NUNCHUK_JOYSTICK_CHANGED; joy.RawX = raw_x; joy.RawY = raw_y; // apply the calibration data wiimote_state::nunchuk::calibration_info &calib = Internal.Nunchuk.CalibrationInfo; if(Internal.Nunchuk.CalibrationInfo.MaxX != 0x00) joy.X = ((float)raw_x - calib.MidX) / ((float)calib.MaxX - calib.MinX); if(calib.MaxY != 0x00) joy.Y = ((float)raw_y - calib.MidY) / ((float)calib.MaxY - calib.MinY); // i prefer the outputs to range -1 - +1 (note this also affects the // deadzone calculations) joy.X *= 2; joy.Y *= 2; // apply the public deadzones to the internal state (if set) joy.DeadZone = Nunchuk.Joystick.DeadZone; ApplyJoystickDeadZones(joy); } } break; case wiimote_state::CLASSIC: case wiimote_state::GH3_GHWT_GUITAR: case wiimote_state::GHWT_DRUMS: { // buttons: WORD bits = *(WORD*)(buff+offset+4); bits = ~bits; // need to invert bits since 0 is down, and 1 is up if(bits != Internal.ClassicController.Button.Bits) changed |= CLASSIC_BUTTONS_CHANGED; Internal.ClassicController.Button.Bits = bits; // joysticks: wiimote_state::joystick &joyL = Internal.ClassicController.JoystickL; wiimote_state::joystick &joyR = Internal.ClassicController.JoystickR; float l_raw_x = (float) (buff[offset+0] & 0x3f); float l_raw_y = (float) (buff[offset+1] & 0x3f); float r_raw_x = (float)((buff[offset+2] >> 7) | ((buff[offset+1] & 0xc0) >> 5) | ((buff[offset+0] & 0xc0) >> 3)); float r_raw_y = (float) (buff[offset+2] & 0x1f); if((joyL.RawX != l_raw_x) || (joyL.RawY != l_raw_y)) changed |= CLASSIC_JOYSTICK_L_CHANGED; if((joyR.RawX != r_raw_x) || (joyR.RawY != r_raw_y)) changed |= CLASSIC_JOYSTICK_R_CHANGED; joyL.RawX = l_raw_x; joyL.RawY = l_raw_y; joyR.RawX = r_raw_x; joyR.RawY = r_raw_y; // apply calibration wiimote_state::classic_controller::calibration_info &calib = Internal.ClassicController.CalibrationInfo; if(calib.MaxXL != 0x00) joyL.X = (joyL.RawX - calib.MidXL) / ((float)calib.MaxXL - calib.MinXL); if(calib.MaxYL != 0x00) joyL.Y = (joyL.RawY - calib.MidYL) / ((float)calib.MaxYL - calib.MinYL); if(calib.MaxXR != 0x00) joyR.X = (joyR.RawX - calib.MidXR) / ((float)calib.MaxXR - calib.MinXR); if(calib.MaxYR != 0x00) joyR.Y = (joyR.RawY - calib.MidYR) / ((float)calib.MaxYR - calib.MinYR); // i prefer the joystick outputs to range -1 - +1 (note this also affects // the deadzone calculations) joyL.X *= 2; joyL.Y *= 2; joyR.X *= 2; joyR.Y *= 2; // apply the public deadzones to the internal state (if set) joyL.DeadZone = ClassicController.JoystickL.DeadZone; joyR.DeadZone = ClassicController.JoystickR.DeadZone; ApplyJoystickDeadZones(joyL); ApplyJoystickDeadZones(joyR); // triggers BYTE raw_trigger_l = ((buff[offset+2] & 0x60) >> 2) | (buff[offset+3] >> 5); BYTE raw_trigger_r = buff[offset+3] & 0x1f; if((raw_trigger_l != Internal.ClassicController.RawTriggerL) || (raw_trigger_r != Internal.ClassicController.RawTriggerR)) changed |= CLASSIC_TRIGGERS_CHANGED; Internal.ClassicController.RawTriggerL = raw_trigger_l; Internal.ClassicController.RawTriggerR = raw_trigger_r; if(calib.MaxTriggerL != 0x00) Internal.ClassicController.TriggerL = (float)Internal.ClassicController.RawTriggerL / ((float)calib.MaxTriggerL - calib.MinTriggerL); if(calib.MaxTriggerR != 0x00) Internal.ClassicController.TriggerR = (float)Internal.ClassicController.RawTriggerR / ((float)calib.MaxTriggerR - calib.MinTriggerR); } break; case BALANCE_BOARD: { wiimote_state::balance_board::sensors_raw prev_raw = Internal.BalanceBoard.Raw; Internal.BalanceBoard.Raw.TopR = (short)((short)buff[offset+0] << 8 | buff[offset+1]); Internal.BalanceBoard.Raw.BottomR = (short)((short)buff[offset+2] << 8 | buff[offset+3]); Internal.BalanceBoard.Raw.TopL = (short)((short)buff[offset+4] << 8 | buff[offset+5]); Internal.BalanceBoard.Raw.BottomL = (short)((short)buff[offset+6] << 8 | buff[offset+7]); if((Internal.BalanceBoard.Raw.TopL != prev_raw.TopL) || (Internal.BalanceBoard.Raw.TopR != prev_raw.TopR) || (Internal.BalanceBoard.Raw.BottomL != prev_raw.BottomL) || (Internal.BalanceBoard.Raw.BottomR != prev_raw.BottomR)) changed |= BALANCE_WEIGHT_CHANGED; Internal.BalanceBoard.Kg.TopL = GetBalanceValue(Internal.BalanceBoard.Raw.TopL, Internal.BalanceBoard.CalibrationInfo.Kg0 .TopL, Internal.BalanceBoard.CalibrationInfo.Kg17.TopL, Internal.BalanceBoard.CalibrationInfo.Kg34.TopL); Internal.BalanceBoard.Kg.TopR = GetBalanceValue(Internal.BalanceBoard.Raw.TopR, Internal.BalanceBoard.CalibrationInfo.Kg0 .TopR, Internal.BalanceBoard.CalibrationInfo.Kg17.TopR, Internal.BalanceBoard.CalibrationInfo.Kg34.TopR); Internal.BalanceBoard.Kg.BottomL = GetBalanceValue(Internal.BalanceBoard.Raw.BottomL, Internal.BalanceBoard.CalibrationInfo.Kg0 .BottomL, Internal.BalanceBoard.CalibrationInfo.Kg17.BottomL, Internal.BalanceBoard.CalibrationInfo.Kg34.BottomL); Internal.BalanceBoard.Kg.BottomR = GetBalanceValue(Internal.BalanceBoard.Raw.BottomR, Internal.BalanceBoard.CalibrationInfo.Kg0 .BottomR, Internal.BalanceBoard.CalibrationInfo.Kg17.BottomR, Internal.BalanceBoard.CalibrationInfo.Kg34.BottomR); // uses these as the 'at rest' offsets? (immediately after Connect(), // or if the app called CalibrateAtRest()) if(bCalibrateAtRest) { bCalibrateAtRest = false; TRACE(_T(".. Auto-removing 'at rest' BBoard offsets.")); Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg; } // remove the 'at rest' offsets Internal.BalanceBoard.Kg.TopL -= BalanceBoard.AtRestKg.TopL; Internal.BalanceBoard.Kg.TopR -= BalanceBoard.AtRestKg.TopR; Internal.BalanceBoard.Kg.BottomL -= BalanceBoard.AtRestKg.BottomL; Internal.BalanceBoard.Kg.BottomR -= BalanceBoard.AtRestKg.BottomR; // compute the average Internal.BalanceBoard.Kg.Total = Internal.BalanceBoard.Kg.TopL + Internal.BalanceBoard.Kg.TopR + Internal.BalanceBoard.Kg.BottomL + Internal.BalanceBoard.Kg.BottomR; // and convert to Lbs const float KG2LB = 2.20462262f; Internal.BalanceBoard.Lb = Internal.BalanceBoard.Kg; Internal.BalanceBoard.Lb.TopL *= KG2LB; Internal.BalanceBoard.Lb.TopR *= KG2LB; Internal.BalanceBoard.Lb.BottomL *= KG2LB; Internal.BalanceBoard.Lb.BottomR *= KG2LB; Internal.BalanceBoard.Lb.Total *= KG2LB; } break; case MOTION_PLUS: { bMotionPlusDetected = true; bMotionPlusEnabled = true; short yaw = ((unsigned short)buff[offset+3] & 0xFC)<<6 | (unsigned short)buff[offset+0]; short pitch = ((unsigned short)buff[offset+5] & 0xFC)<<6 | (unsigned short)buff[offset+2]; short roll = ((unsigned short)buff[offset+4] & 0xFC)<<6 | (unsigned short)buff[offset+1]; // we get one set of bogus values when the MotionPlus is disconnected, // so ignore them if((yaw != 0x3fff) || (pitch != 0x3fff) || (roll != 0x3fff)) { wiimote_state::motion_plus::sensors_raw &raw = Internal.MotionPlus.Raw; if((raw.Yaw != yaw) || (raw.Pitch != pitch) || (raw.Roll != roll)) changed |= MOTIONPLUS_SPEED_CHANGED; raw.Yaw = yaw; raw.Pitch = pitch; raw.Roll = roll; // convert to float values bool yaw_slow = (buff[offset+3] & 0x2) == 0x2; bool pitch_slow = (buff[offset+3] & 0x1) == 0x1; bool roll_slow = (buff[offset+4] & 0x2) == 0x2; float y_scale = yaw_slow? 0.05f : 0.25f; float p_scale = pitch_slow? 0.05f : 0.25f; float r_scale = roll_slow? 0.05f : 0.25f; Internal.MotionPlus.Speed.Yaw = -(raw.Yaw - 0x1F7F) * y_scale; Internal.MotionPlus.Speed.Pitch = -(raw.Pitch - 0x1F7F) * p_scale; Internal.MotionPlus.Speed.Roll = -(raw.Roll - 0x1F7F) * r_scale; // show if there's an extension plugged into the MotionPlus: bool extension = buff[offset+4] & 1; if(extension != bMotionPlusExtension) { if(extension) { TRACE(_T(".. MotionPlus extension found.")); changed |= MOTIONPLUS_EXTENSION_CONNECTED; } else{ TRACE(_T(".. MotionPlus' extension disconnected.")); changed |= MOTIONPLUS_EXTENSION_DISCONNECTED; } } bMotionPlusExtension = extension; } // while we're getting data, the plus is obviously detected/enabled // bMotionPlusDetected = bMotionPlusEnabled = true; } break; } return changed; } // ------------------------------------------------------------------------------------ int wiimote::ParseReadAddress (BYTE* buff) { // decode the address that was queried: int address = buff[4]<<8 | buff[5]; int size = buff[3] >> 4; int changed = 0; if((buff[3] & 0x08) != 0) { WARN(_T("error: read address not valid.")); _ASSERT(0); return NO_CHANGE; } // address read failed (write-only)? else if((buff[3] & 0x07) != 0) { // this also happens when attempting to detect a non-existant MotionPlus if(MotionPlusDetectCount) { --MotionPlusDetectCount; if(Internal.ExtensionType == MOTION_PLUS) { if(bMotionPlusDetected) TRACE(_T(".. MotionPlus removed.")); bMotionPlusDetected = false; bMotionPlusEnabled = false; // the MotionPlus can sometimes get confused - initializing // extenions fixes it: // if(address == 0xfa) // InitializeExtension(); } } else WARN(_T("error: attempt to read from write-only register 0x%X."), buff[3]); return NO_CHANGE; } // *NOTE*: this is a major (but convenient) hack! The returned data only // contains the lower two bytes of the address that was queried. // as these don't collide between any of the addresses/registers // we currently read, it's OK to match just those two bytes // skip the header buff += 6; switch(address) { case (REGISTER_CALIBRATION & 0xffff): { _ASSERT(size == 6); TRACE(_T(".. got wiimote calibration.")); Internal.CalibrationInfo.X0 = buff[0]; Internal.CalibrationInfo.Y0 = buff[1]; Internal.CalibrationInfo.Z0 = buff[2]; Internal.CalibrationInfo.XG = buff[4]; Internal.CalibrationInfo.YG = buff[5]; Internal.CalibrationInfo.ZG = buff[6]; //changed |= CALIBRATION_CHANGED; } break; // note: this covers both the normal extension and motion plus extension // addresses (0x4a400fa / 0x4a600fa) case (REGISTER_EXTENSION_TYPE & 0xffff): { _ASSERT(size == 5); QWORD type = *(QWORD*)buff; // TRACE(_T("(found extension 0x%I64x)"), type); static const QWORD NUNCHUK = 0x000020A40000ULL; static const QWORD CLASSIC = 0x010120A40000ULL; static const QWORD GH3_GHWT_GUITAR = 0x030120A40000ULL; static const QWORD GHWT_DRUMS = 0x030120A40001ULL; static const QWORD BALANCE_BOARD = 0x020420A40000ULL; static const QWORD MOTION_PLUS = 0x050420A40000ULL; static const QWORD MOTION_PLUS_DETECT = 0x050020a60000ULL; static const QWORD MOTION_PLUS_DETECT2 = 0x050420a60000ULL; static const QWORD PARTIALLY_INSERTED = 0xffffffffffffULL; // MotionPlus: _before_ it's been activated if((type == MOTION_PLUS_DETECT) || (type == MOTION_PLUS_DETECT2)) { if(!bMotionPlusDetected) { TRACE(_T("Motion Plus detected!")); changed |= MOTIONPLUS_DETECTED; } bMotionPlusDetected = true; --MotionPlusDetectCount; break; } #define IF_TYPE(id) if(type == id) { \ /* sometimes it comes in more than once */ \ if(Internal.ExtensionType == wiimote_state::id)\ break; \ Internal.ExtensionType = wiimote_state::id; // MotionPlus: once it's activated & mapped to the standard ext. port IF_TYPE(MOTION_PLUS) TRACE(_T(".. Motion Plus!")); // and start a query for the calibration data ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); bMotionPlusDetected = true; } else IF_TYPE(NUNCHUK) TRACE(_T(".. Nunchuk!")); bMotionPlusEnabled = false; // and start a query for the calibration data ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); } else IF_TYPE(CLASSIC) TRACE(_T(".. Classic Controller!")); bMotionPlusEnabled = false; // and start a query for the calibration data ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); } else IF_TYPE(GH3_GHWT_GUITAR) // sometimes it comes in more than once? TRACE(_T(".. GH3/GHWT Guitar Controller!")); bMotionPlusEnabled = false; // and start a query for the calibration data ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); } else IF_TYPE(GHWT_DRUMS) TRACE(_T(".. GHWT Drums!")); bMotionPlusEnabled = false; // and start a query for the calibration data ReadAddress(REGISTER_EXTENSION_CALIBRATION, 16); } else IF_TYPE(BALANCE_BOARD) TRACE(_T(".. Balance Board!")); bMotionPlusEnabled = false; // and start a query for the calibration data ReadAddress(REGISTER_BALANCE_CALIBRATION, 24); } else if(type == PARTIALLY_INSERTED) { // sometimes it comes in more than once? if(Internal.ExtensionType == wiimote_state::PARTIALLY_INSERTED) Sleep(50); TRACE(_T(".. partially inserted!")); bMotionPlusEnabled = false; Internal.ExtensionType = wiimote_state::PARTIALLY_INSERTED; changed |= EXTENSION_PARTIALLY_INSERTED; // try initializing the extension again by requesting another // status report (this usually fixes it) Internal.bExtension = false; RequestStatusReport(); } else{ TRACE(_T("unknown extension controller found (0x%I64x)"), type); } } break; case (REGISTER_EXTENSION_CALIBRATION & 0xffff): case (REGISTER_BALANCE_CALIBRATION & 0xffff): { // _ASSERT(((Internal.ExtensionType == BALANCE_BOARD) && (size == 31)) || // ((Internal.ExtensionType != BALANCE_BOARD) && (size == 15))); switch(Internal.ExtensionType) { case wiimote_state::NUNCHUK: { wiimote_state::nunchuk::calibration_info &calib = Internal.Nunchuk.CalibrationInfo; calib.X0 = buff[ 0]; calib.Y0 = buff[ 1]; calib.Z0 = buff[ 2]; calib.XG = buff[ 4]; calib.YG = buff[ 5]; calib.ZG = buff[ 6]; calib.MaxX = buff[ 8]; calib.MinX = buff[ 9]; calib.MidX = buff[10]; calib.MaxY = buff[11]; calib.MinY = buff[12]; calib.MidY = buff[13]; changed |= NUNCHUK_CONNECTED;//|NUNCHUK_CALIBRATION_CHANGED; // reenable reports // SetReportType(ReportType); } break; case wiimote_state::CLASSIC: case wiimote_state::GH3_GHWT_GUITAR: case wiimote_state::GHWT_DRUMS: { wiimote_state::classic_controller::calibration_info &calib = Internal.ClassicController.CalibrationInfo; calib.MaxXL = buff[ 0] >> 2; calib.MinXL = buff[ 1] >> 2; calib.MidXL = buff[ 2] >> 2; calib.MaxYL = buff[ 3] >> 2; calib.MinYL = buff[ 4] >> 2; calib.MidYL = buff[ 5] >> 2; calib.MaxXR = buff[ 6] >> 3; calib.MinXR = buff[ 7] >> 3; calib.MidXR = buff[ 8] >> 3; calib.MaxYR = buff[ 9] >> 3; calib.MinYR = buff[10] >> 3; calib.MidYR = buff[11] >> 3; // this doesn't seem right... // calib.MinTriggerL = buff[12] >> 3; // calib.MaxTriggerL = buff[14] >> 3; // calib.MinTriggerR = buff[13] >> 3; // calib.MaxTriggerR = buff[15] >> 3; calib.MinTriggerL = 0; calib.MaxTriggerL = 31; calib.MinTriggerR = 0; calib.MaxTriggerR = 31; changed |= CLASSIC_CONNECTED;//|CLASSIC_CALIBRATION_CHANGED; // reenable reports // SetReportType(ReportType); } break; case BALANCE_BOARD: { // first part, 0 & 17kg calibration values wiimote_state::balance_board::calibration_info &calib = Internal.BalanceBoard.CalibrationInfo; calib.Kg0 .TopR = (short)((short)buff[0] << 8 | buff[1]); calib.Kg0 .BottomR = (short)((short)buff[2] << 8 | buff[3]); calib.Kg0 .TopL = (short)((short)buff[4] << 8 | buff[5]); calib.Kg0 .BottomL = (short)((short)buff[6] << 8 | buff[7]); calib.Kg17.TopR = (short)((short)buff[8] << 8 | buff[9]); calib.Kg17.BottomR = (short)((short)buff[10] << 8 | buff[11]); calib.Kg17.TopL = (short)((short)buff[12] << 8 | buff[13]); calib.Kg17.BottomL = (short)((short)buff[14] << 8 | buff[15]); // 2nd part is scanned above } break; case MOTION_PLUS: { // TODO: not known how the calibration values work changed |= MOTIONPLUS_ENABLED; bMotionPlusEnabled = true; bInitInProgress = false; // reenable reports // SetReportType(ReportType); } break; } case 0x34: { if(Internal.ExtensionType == BALANCE_BOARD) { wiimote_state::balance_board::calibration_info &calib = Internal.BalanceBoard.CalibrationInfo; // 2nd part of the balance board calibration, // 34kg calibration values calib.Kg34.TopR = (short)((short)buff[0] << 8 | buff[1]); calib.Kg34.BottomR = (short)((short)buff[2] << 8 | buff[3]); calib.Kg34.TopL = (short)((short)buff[4] << 8 | buff[5]); calib.Kg34.BottomL = (short)((short)buff[6] << 8 | buff[7]); changed |= BALANCE_CONNECTED; // reenable reports SetReportType(IN_BUTTONS_BALANCE_BOARD); } // else unknown what these are for } bInitInProgress = false; } break; default: // _ASSERT(0); // shouldn't happen break; } return changed; } // ------------------------------------------------------------------------------------ void wiimote::ReadCalibration () { TRACE(_T("Requestion wiimote calibration:")); // this appears to change the report type to 0x31 ReadAddress(REGISTER_CALIBRATION, 7); } // ------------------------------------------------------------------------------------ void wiimote::EnableIR (wiimote_state::ir::mode mode) { Internal.IR.Mode = mode; BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_IR; buff[1] = 0x04 | GetRumbleBit(); WriteReport(buff); memset(buff, 0, REPORT_LENGTH); buff[0] = OUT_IR2; buff[1] = 0x04 | GetRumbleBit(); WriteReport(buff); static const BYTE ir_sens1[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xc0}; static const BYTE ir_sens2[] = {0x40, 0x00}; WriteData(REGISTER_IR, 0x08); Sleep(25); // wait a little to make IR more reliable (for some) WriteData(REGISTER_IR_SENSITIVITY_1, sizeof(ir_sens1), ir_sens1); WriteData(REGISTER_IR_SENSITIVITY_2, sizeof(ir_sens2), ir_sens2); WriteData(REGISTER_IR_MODE, (BYTE)mode); } // ------------------------------------------------------------------------------------ void wiimote::DisableIR () { Internal.IR.Mode = wiimote_state::ir::OFF; BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_IR; buff[1] = GetRumbleBit(); WriteReport(buff); memset(buff, 0, REPORT_LENGTH); buff[0] = OUT_IR2; buff[1] = GetRumbleBit(); WriteReport(buff); } // ------------------------------------------------------------------------------------ unsigned __stdcall wiimote::HIDwriteThreadfunc (void* param) { _ASSERT(param); TRACE(_T("(starting HID write thread)")); wiimote &remote = *(wiimote*)param; while(remote.Handle != INVALID_HANDLE_VALUE) { // try to write the oldest entry in the queue #ifdef USE_DYNAMIC_HIDQUEUE if(!remote.HIDwriteQueue.empty()) #else if(!remote.HID.IsEmpty()) #endif { #ifdef BEEP_DEBUG_WRITES Beep(1500,1); #endif EnterCriticalSection(&remote.HIDwriteQueueLock); #ifdef USE_DYNAMIC_HIDQUEUE BYTE *buff = remote.HIDwriteQueue.front(); _ASSERT(buff); #else BYTE *buff = remote.HID.Queue[remote.HID.ReadIndex].Report; #endif LeaveCriticalSection(&remote.HIDwriteQueueLock); if(!_HidD_SetOutputReport(remote.Handle, buff, REPORT_LENGTH)) { DWORD err = GetLastError(); if(err==ERROR_BUSY) TRACE(_T("**** HID WRITE: BUSY ****")); else if(err == ERROR_NOT_READY) TRACE(_T("**** HID WRITE: NOT READY ****")); if((err != ERROR_BUSY) && // "the requested resource is in use" (err != ERROR_NOT_READY)) // "the device is not ready" { if(err == ERROR_NOT_SUPPORTED) { WARN(_T("BT Stack doesn't suport HID writes!")); goto remove_entry; } else{ DEEP_TRACE(_T("HID write failed (err %u)! - "), err); // if this worked previously, the connection was probably lost if(remote.IsConnected()) remote.bConnectionLost = true; } //_T("aborting write thread"), err); //return 911; } } else{ remove_entry: EnterCriticalSection(&remote.HIDwriteQueueLock); #ifdef USE_DYNAMIC_HIDQUEUE remote.HIDwriteQueue.pop(); delete[] buff; #else remote.HID.ReadIndex++; remote.HID.ReadIndex &= (hid::MAX_QUEUE_ENTRIES-1); #endif LeaveCriticalSection(&remote.HIDwriteQueueLock); } } Sleep(1); } TRACE(_T("ending HID write thread")); return 0; } // ------------------------------------------------------------------------------------ bool wiimote::WriteReport (BYTE *buff) { #ifdef BEEP_DEBUG_WRITES Beep(2000,1); #endif #ifdef _DEBUG #define DEEP_TRACE_TYPE(type) case OUT_##type: DEEP_TRACE(_T("WriteReport: ")\ _T(#type)); break switch(buff[0]) { DEEP_TRACE_TYPE(NONE); DEEP_TRACE_TYPE(LEDs); DEEP_TRACE_TYPE(TYPE); DEEP_TRACE_TYPE(IR); DEEP_TRACE_TYPE(SPEAKER_ENABLE); DEEP_TRACE_TYPE(STATUS); DEEP_TRACE_TYPE(WRITEMEMORY); DEEP_TRACE_TYPE(READMEMORY); DEEP_TRACE_TYPE(SPEAKER_DATA); DEEP_TRACE_TYPE(SPEAKER_MUTE); DEEP_TRACE_TYPE(IR2); default: TRACE(_T("WriteReport: type [%02x][%02x]"), buff[1], buff[2]); } #endif if(bUseHIDwrite) { // HidD_SetOutputReport: +: works on MS Bluetooth stacks (WriteFile doesn't). // -: is synchronous, so make it async if(!HIDwriteThread) { HIDwriteThread = (HANDLE)_beginthreadex(NULL, 0, HIDwriteThreadfunc, this, 0, NULL); _ASSERT(HIDwriteThread); if(!HIDwriteThread) { WARN(_T("couldn't create HID write thread!")); return false; } SetThreadPriority(HIDwriteThread, WORKER_THREAD_PRIORITY); } // insert the write request into the thread's queue #ifdef USE_DYNAMIC_HIDQUEUE EnterCriticalSection(&HIDwriteQueueLock); BYTE *buff_copy = new BYTE[REPORT_LENGTH]; #else // allocate the HID write queue once if(!HID.Queue && !HID.Allocate()) return false; EnterCriticalSection(&HIDwriteQueueLock); BYTE *buff_copy = HID.Queue[HID.WriteIndex].Report; #endif memcpy(buff_copy, buff, REPORT_LENGTH); #ifdef USE_DYNAMIC_HIDQUEUE HIDwriteQueue.push(buff_copy); #else HID.WriteIndex++; HID.WriteIndex &= (HID.MAX_QUEUE_ENTRIES-1); // check if the fixed report queue has overflown: // if this ASSERT triggers, the HID write queue (that stores reports // for asynchronous output by HIDwriteThreadfunc) has overflown. // this can happen if the connection with the wiimote has been lost // and in that case is harmless. // // if it happens during normal operation though you need to increase // hid::MAX_QUEUE_ENTRIES to the next power-of-2 (see comments) // _and_ email me the working setting so I can update the next release _ASSERT(HID.WriteIndex != HID.ReadIndex); #endif LeaveCriticalSection(&HIDwriteQueueLock); return true; } // WriteFile: DWORD written; if(!WriteFile(Handle, buff, REPORT_LENGTH, &written, &Overlapped)) { DWORD error = GetLastError(); if(error != ERROR_IO_PENDING) { TRACE(_T("WriteFile failed, err: %u!"), error); // if it worked previously, assume we lost the connection if(IsConnected()) bConnectionLost = true; #ifndef USE_DYNAMIC_HIDQUEUE HID.Deallocate(); #endif return false; } } return true; } // ------------------------------------------------------------------------------------ // experimental speaker support: // ------------------------------------------------------------------------------------ bool wiimote::MuteSpeaker (bool on) { _ASSERT(IsConnected()); if(!IsConnected()) return false; if(Internal.Speaker.bMuted == on) return true; if(on) TRACE(_T("muting speaker." )); else TRACE(_T("unmuting speaker.")); BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_SPEAKER_MUTE; buff[1] = (on? 0x04 : 0x00) | GetRumbleBit(); if(!WriteReport(buff)) return false; Sleep(1); Internal.Speaker.bMuted = on; return true; } // ------------------------------------------------------------------------------------ bool wiimote::EnableSpeaker (bool on) { _ASSERT(IsConnected()); if(!IsConnected()) return false; if(Internal.Speaker.bEnabled == on) return true; if(on) TRACE(_T("enabling speaker.")); else TRACE(_T("disabling speaker.")); BYTE buff [REPORT_LENGTH] = {0}; buff[0] = OUT_SPEAKER_ENABLE; buff[1] = (on? 0x04 : 0x00) | GetRumbleBit(); if(!WriteReport(buff)) return false; if(!on) { Internal.Speaker.Freq = FREQ_NONE; Internal.Speaker.Volume = 0; MuteSpeaker(true); } Internal.Speaker.bEnabled = on; return true; } // ------------------------------------------------------------------------------------ #ifdef TR4 // TEMP, ignore extern int hzinc; #endif // ------------------------------------------------------------------------------------ unsigned __stdcall wiimote::SampleStreamThreadfunc (void* param) { TRACE(_T("(starting sample thread)")); // sends a simple square wave sample stream wiimote &remote = *(wiimote*)param; static BYTE squarewave_report[REPORT_LENGTH] = { OUT_SPEAKER_DATA, 20<<3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, }; static BYTE sample_report [REPORT_LENGTH] = { OUT_SPEAKER_DATA, 0 }; bool last_playing = false; DWORD frame = 0; DWORD frame_start = 0; unsigned total_samples = 0; unsigned sample_index = 0; wiimote_sample *current_sample = NULL; // TODO: duration!! while(remote.IsConnected()) { bool playing = remote.IsPlayingAudio(); if(!playing) Sleep(1); else{ const unsigned freq_hz = FreqLookup[remote.Internal.Speaker.Freq]; #ifdef TR4 const float frame_ms = 1000 / ((freq_hz+hzinc) / 40.f); // 20bytes = 40 samples per write #else const float frame_ms = 1000 / (freq_hz / 40.f); // 20bytes = 40 samples per write #endif // has the sample just changed? bool sample_changed = (current_sample != remote.CurrentSample); current_sample = (wiimote_sample*)remote.CurrentSample; // (attempts to minimise glitches, doesn't seem to help though) //#define FIRSTFRAME_IS_SILENT // send all-zero for first frame #ifdef FIRSTFRAME_IS_SILENT bool silent_frame = false; #endif if(!last_playing || sample_changed) { frame = 0; frame_start = timeGetTime(); total_samples = current_sample? current_sample->length : 0; sample_index = 0; #ifdef FIRSTFRAME_IS_SILENT silent_frame = true; #endif } // are we streaming a sample? if(current_sample) { if(sample_index < current_sample->length) { // (remember that samples are 4bit, ie. 2 per byte) unsigned samples_left = (current_sample->length - sample_index); unsigned report_samples = min(samples_left, (unsigned)40); // round the entries up to the nearest multiple of 2 unsigned report_entries = (report_samples+1) >> 1; sample_report[1] = (BYTE)((report_entries<<3) | remote.GetRumbleBit()); #ifdef FIRSTFRAME_IS_SILENT if(silent_frame) { // send all-zeroes for(unsigned index=0; indexsamples[(sample_index>>1)+index]; remote.WriteReport(sample_report); sample_index += report_samples; } } else{ // we reached the sample end remote.CurrentSample = NULL; current_sample = NULL; remote.Internal.Speaker.Freq = FREQ_NONE; remote.Internal.Speaker.Volume = 0; } } // no, a squarewave else{ squarewave_report[1] = (20<<3) | remote.GetRumbleBit(); remote.WriteReport(squarewave_report); #if 0 // verify that we're sending at the correct rate (we are) DWORD elapsed = (timeGetTime()-frame_start); unsigned total_samples = frame * 40; float elapsed_secs = elapsed / 1000.f; float sent_persec = total_samples / elapsed_secs; #endif } frame++; // send the first two buffers immediately? (attempts to lessen startup // startup glitches by assuming we're filling a small sample // (or general input) buffer on the wiimote) - doesn't seem to help // if(frame > 2) { while((timeGetTime()-frame_start) < (unsigned)(frame*frame_ms)) Sleep(1); // } } last_playing = playing; } TRACE(_T("(ending sample thread)")); return 0; } // ------------------------------------------------------------------------------------ bool wiimote::Load16bitMonoSampleWAV (const TCHAR* filepath, wiimote_sample &out) { // converts unsigned 16bit mono .wav audio data to the 4bit ADPCM variant // used by the Wiimote (at least the closest match so far), and returns // the data in a BYTE array (caller must delete[] it when no longer needed): memset(&out, 0, sizeof(out)); TRACE(_T("Loading '%s'"), filepath); FILE *file; #if (_MSC_VER >= 1400) // VC 2005+ _tfopen_s(&file, filepath, _T("rb")); #else file = _tfopen(filepath, _T("rb")); #endif _ASSERT(file); if(!file) { WARN(_T("Couldn't open '%s"), filepath); return false; } // parse the .wav file struct riff_chunkheader { char ckID [4]; DWORD ckSize; char formType [4]; }; struct chunk_header { char ckID [4]; DWORD ckSize; }; union { WAVEFORMATEX x; WAVEFORMATEXTENSIBLE xe; } wf = {0}; riff_chunkheader riff_chunkheader; chunk_header chunk_header; speaker_freq freq = FREQ_NONE; #define READ(data) if(fread(&data, sizeof(data), 1, file) != 1) { \ TRACE(_T(".wav file corrupt")); \ fclose(file); \ return false; \ } #define READ_SIZE(ptr,size) if(fread(ptr, size, 1, file) != 1) { \ TRACE(_T(".wav file corrupt")); \ fclose(file); \ return false; \ } // read the riff chunk header READ(riff_chunkheader); // valid RIFF file? _ASSERT(!strncmp(riff_chunkheader.ckID, "RIFF", 4)); if(strncmp(riff_chunkheader.ckID, "RIFF", 4)) goto unsupported; // nope // valid WAV variant? _ASSERT(!strncmp(riff_chunkheader.formType, "WAVE", 4)); if(strncmp(riff_chunkheader.formType, "WAVE", 4)) goto unsupported; // nope // find the format & data chunks while(1) { READ(chunk_header); if(!strncmp(chunk_header.ckID, "fmt ", 4)) { // not a valid .wav file? if(chunk_header.ckSize < 16 || chunk_header.ckSize > sizeof(WAVEFORMATEXTENSIBLE)) goto unsupported; READ_SIZE((BYTE*)&wf.x, chunk_header.ckSize); // now we know it's true wav file bool extensible = (wf.x.wFormatTag == WAVE_FORMAT_EXTENSIBLE); int format = extensible? wf.xe.SubFormat.Data1 : wf.x .wFormatTag; // must be uncompressed PCM (the format comparisons also work on // the 'extensible' header, even though they're named differently) if(format != WAVE_FORMAT_PCM) { TRACE(_T(".. not uncompressed PCM")); goto unsupported; } // must be mono, 16bit if((wf.x.nChannels != 1) || (wf.x.wBitsPerSample != 16)) { TRACE(_T(".. %d bit, %d channel%s"), wf.x.wBitsPerSample, wf.x.nChannels, (wf.x.nChannels>1? _T("s"):_T(""))); goto unsupported; } // must be _near_ a supported speaker frequency range (but allow some // tolerance, especially as the speaker freq values aren't final yet): unsigned sample_freq = wf.x.nSamplesPerSec; const unsigned epsilon = 100; // for now for(unsigned index=1; index= FreqLookup[index] && (sample_freq-epsilon) <= FreqLookup[index]) { freq = (speaker_freq)index; TRACE(_T(".. using speaker freq %u"), FreqLookup[index]); break; } } if(freq == FREQ_NONE) { WARN(_T("Couldn't (loosely) match .wav samplerate %u Hz to speaker"), sample_freq); goto unsupported; } } else if(!strncmp(chunk_header.ckID, "data", 4)) { // make sure we got a valid fmt chunk first if(!wf.x.nBlockAlign) goto corrupt_file; // grab the data unsigned total_samples = chunk_header.ckSize / wf.x.nBlockAlign; if(total_samples == 0) goto corrupt_file; short *samples = new short[total_samples]; size_t read = fread(samples, 2, total_samples, file); fclose(file); if(read != total_samples) { if(read == 0) { delete[] samples; goto corrupt_file; } // got a different number, but use them anyway WARN(_T("found %s .wav audio data than expected (%u/%u samples)"), ((read < total_samples)? _T("less") : _T("more")), read, total_samples); total_samples = read; } // and convert them bool res = Convert16bitMonoSamples(samples, true, total_samples, freq, out); delete[] samples; return res; } else{ // unknown chunk, skip its data DWORD chunk_bytes = (chunk_header.ckSize + 1) & ~1L; if(fseek(file, chunk_bytes, SEEK_CUR)) goto corrupt_file; } } corrupt_file: WARN(_T(".wav file is corrupt")); fclose(file); return false; unsupported: WARN(_T(".wav file format not supported (must be mono 16bit PCM)")); fclose(file); return false; } // ------------------------------------------------------------------------------------ bool wiimote::Load16BitMonoSampleRAW (const TCHAR* filepath, bool _signed, speaker_freq freq, wiimote_sample &out) { // converts (.wav style) unsigned 16bit mono raw data to the 4bit ADPCM variant // used by the Wiimote, and returns the data in a BYTE array (caller must // delete[] it when no longer needed): memset(&out, 0, sizeof(out)); // get the length of the file struct _stat file_info; if(_tstat(filepath, &file_info)) { WARN(_T("couldn't get filesize for '%s'"), filepath); return false; } DWORD len = file_info.st_size; _ASSERT(len); if(!len) { WARN(_T("zero-size sample file '%s'"), filepath); return false; } unsigned total_samples = (len+1) / 2; // round up just in case file is corrupt // allocate a buffer to hold the samples to convert short *samples = new short[total_samples]; _ASSERT(samples); if(!samples) { TRACE(_T("Couldn't open '%s"), filepath); return false; } // load them FILE *file; bool res; #if (_MSC_VER >= 1400) // VC 2005+ _tfopen_s(&file, filepath, _T("rb")); #else file = _tfopen(filepath, _T("rb")); #endif _ASSERT(file); if(!file) { TRACE(_T("Couldn't open '%s"), filepath); goto error; } res = (fread(samples, 1, len, file) == len); fclose(file); if(!res) { WARN(_T("Couldn't load file '%s'"), filepath); goto error; } // and convert them res = Convert16bitMonoSamples(samples, _signed, total_samples, freq, out); delete[] samples; return res; error: delete[] samples; return false; } // ------------------------------------------------------------------------------------ bool wiimote::Convert16bitMonoSamples (const short* samples, bool _signed, DWORD length, speaker_freq freq, wiimote_sample &out) { // converts 16bit mono sample data to the native 4bit format used by the Wiimote, // and returns the data in a BYTE array (caller must delete[] when no // longer needed): memset(&out, 0, sizeof(0)); _ASSERT(samples && length); if(!samples || !length) return false; // allocate the output buffer out.samples = new BYTE[length]; _ASSERT(out.samples); if(!out.samples) return false; // clear it memset(out.samples, 0, length); out.length = length; out.freq = freq; // ADPCM code, adapted from // http://www.wiindows.org/index.php/Talk:Wiimote#Input.2FOutput_Reports static const int index_table[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; static const int diff_table [16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, 15 }; static const int step_scale [16] = { 230, 230, 230, 230, 307, 409, 512, 614, 230, 230, 230, 230, 307, 409, 512, 614 }; // Encode to ADPCM, on initialization set adpcm_prev_value to 0 and adpcm_step // to 127 (these variables must be preserved across reports) int adpcm_prev_value = 0; int adpcm_step = 127; for(size_t i=0; i 7) diff = 7; encoded_val |= diff; adpcm_prev_value += ((adpcm_step * diff_table[encoded_val]) / 8); if(adpcm_prev_value > 0x7fff) adpcm_prev_value = 0x7fff; if(adpcm_prev_value < -0x8000) adpcm_prev_value = -0x8000; adpcm_step = (adpcm_step * step_scale[encoded_val]) >> 8; if(adpcm_step < 127) adpcm_step = 127; if(adpcm_step > 24567) adpcm_step = 24567; if(i & 1) out.samples[i>>1] |= encoded_val; else out.samples[i>>1] |= encoded_val << 4; } return true; } // ------------------------------------------------------------------------------------ bool wiimote::PlaySample (const wiimote_sample &sample, BYTE volume, speaker_freq freq_override) { _ASSERT(IsConnected()); if(!IsConnected()) return false; speaker_freq freq = freq_override? freq_override : sample.freq; TRACE(_T("playing sample.")); EnableSpeaker(true); MuteSpeaker (true); #if 0 // combine everything into one write - faster, seems to work? BYTE bytes[9] = { 0x00, 0x00, 0x00, 10+freq, vol, 0x00, 0x00, 0x01, 0x01 }; WriteData(0x04a20001, sizeof(bytes), bytes); #else // Write 0x01 to register 0x04a20009 WriteData(0x04a20009, 0x01); // Write 0x08 to register 0x04a20001 WriteData(0x04a20001, 0x08); // Write 7-byte configuration to registers 0x04a20001-0x04a20008 BYTE bytes[7] = { 0x00, 0x00, 0x00, 10+(BYTE)freq, volume, 0x00, 0x00 }; WriteData(0x04a20001, sizeof(bytes), bytes); // + Write 0x01 to register 0x04a20008 WriteData(0x04a20008, 0x01); #endif Internal.Speaker.Freq = freq; Internal.Speaker.Volume = volume; CurrentSample = &sample; MuteSpeaker(false); return StartSampleThread(); } // ------------------------------------------------------------------------------------ bool wiimote::StartSampleThread () { if(SampleThread) return true; SampleThread = (HANDLE)_beginthreadex(NULL, 0, SampleStreamThreadfunc, this, 0, NULL); _ASSERT(SampleThread); if(!SampleThread) { WARN(_T("couldn't create sample thread!")); MuteSpeaker (true); EnableSpeaker(false); return false; } SetThreadPriority(SampleThread, WORKER_THREAD_PRIORITY); return true; } // ------------------------------------------------------------------------------------ bool wiimote::PlaySquareWave (speaker_freq freq, BYTE volume) { _ASSERT(IsConnected()); if(!IsConnected()) return false; // if we're already playing a sample, stop it first if(IsPlayingSample()) CurrentSample = NULL; // if we're already playing a square wave at this freq and volume, return else if(IsPlayingAudio() && (Internal.Speaker.Freq == freq) && (Internal.Speaker.Volume == volume)) return true; TRACE(_T("playing square wave.")); // stop playing samples CurrentSample = 0; EnableSpeaker(true); MuteSpeaker (true); #if 0 // combined everything into one write - much faster, seems to work? BYTE bytes[9] = { 0x00, 0x00, 0x00, freq, volume, 0x00, 0x00, 0x01, 0x1 }; WriteData(0x04a20001, sizeof(bytes), bytes); #else // write 0x01 to register 0xa20009 WriteData(0x04a20009, 0x01); // write 0x08 to register 0xa20001 WriteData(0x04a20001, 0x08); // write default sound mode (4bit ADPCM, we assume) 7-byte configuration // to registers 0xa20001-0xa20008 BYTE bytes[7] = { 0x00, 0x00, 0x00, 10+(BYTE)freq, volume, 0x00, 0x00 }; WriteData(0x04a20001, sizeof(bytes), bytes); // write 0x01 to register 0xa20008 WriteData(0x04a20008, 0x01); #endif Internal.Speaker.Freq = freq; Internal.Speaker.Volume = volume; MuteSpeaker(false); return StartSampleThread(); } // ------------------------------------------------------------------------------------ void wiimote::RecordState (state_history &events_out, unsigned max_time_ms, state_change_flags change_trigger) { // user being naughty? if(Recording.bEnabled) StopRecording(); // clear the list if(!events_out.empty()) events_out.clear(); // start recording Recording.StateHistory = &events_out; Recording.StartTimeMS = timeGetTime(); Recording.EndTimeMS = Recording.StartTimeMS + max_time_ms; Recording.TriggerFlags = change_trigger; // as this call happens outside the read/parse thread, set the boolean // which will enable reocrding last, so that all params are in place. // TODO: * stricly speaking this only works on VC2005+ or better, as it // automatically places a memory barrier on volatile variables - earlier/ // other compilers may reorder the assignments!). * Recording.bEnabled = true; } // ------------------------------------------------------------------------------------ void wiimote::StopRecording () { if(!Recording.bEnabled) return; Recording.bEnabled = false; // make sure the read/parse thread has time to notice the change (else it might // still write one more state to the list) Sleep(10); // too much? } // ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------ diff --git a/Modules/InputDevices/WiiMote/wiiyourself/wiimote.h b/Modules/InputDevices/WiiMote/wiiyourself/wiimote.h index 84d6b845d1..b7c0769f16 100644 --- a/Modules/InputDevices/WiiMote/wiiyourself/wiimote.h +++ b/Modules/InputDevices/WiiMote/wiiyourself/wiimote.h @@ -1,495 +1,510 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ // _______________________________________________________________________________ // -// - WiiYourself! - native C++ Wiimote library v1.15 -// (c) gl.tter 2007-10 - http://gl.tter.org +// - WiiYourself! - native C++ Wiimote library v1.15 +// (c) gl.tter 2007-10 - http://gl.tter.org // -// see License.txt for conditions of use. see History.txt for change log. +// see License.txt for conditions of use. see History.txt for change log. // _______________________________________________________________________________ // // wiimote.h (tab = 4 spaces) #ifdef _MSC_VER // VC # pragma once #endif #ifndef _WIIMOTE_H # define _WIIMOTE_H #define WIN32_LEAN_AND_MEAN #include -#include // auto Unicode/Ansi support -#include // for HID write method -#include // for state recording +#include // auto Unicode/Ansi support +#include // for HID write method +#include // for state recording #ifndef QWORD typedef unsigned __int64 QWORD; #endif -#ifdef _MSC_VER // VC-specific: _DEBUG build only _ASSERT() sanity checks +#ifdef _MSC_VER // VC-specific: _DEBUG build only _ASSERT() sanity checks # include #elif defined(__MINGW32__) // define NDEBUG to disable assert # include # define _ASSERT assert #else # define _ASSERT(x) ((void)0) // (add your compiler's implementation if you like) #endif -// #ifdef SWIGWRAPPER // Python Wrapper +// #ifdef SWIGWRAPPER // Python Wrapper // #include "Python/wiimote_state.i" // #else #include "wiimote_state.h" // #endif // configs: //#define USE_DYNAMIC_HIDQUEUE // deprecated // we request periodic status report updates to refresh the battery level // and to detect connection loss (through failed writes) -#define REQUEST_STATUS_EVERY_MS 1000 -#define DETECT_MPLUS_EVERY_MS 1000 -#define DETECT_MPLUS_COUNT 1 // # of tries in quick succession +#define REQUEST_STATUS_EVERY_MS 1000 +#define DETECT_MPLUS_EVERY_MS 1000 +#define DETECT_MPLUS_COUNT 1 // # of tries in quick succession // all threads (read/parse, audio streaming, async rumble...) use this priority -#define WORKER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST +#define WORKER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST // internals -#define WIIYOURSELF_VERSION_MAJOR 1 -#define WIIYOURSELF_VERSION_MINOR1 1 -#define WIIYOURSELF_VERSION_MINOR2 5 -//#define WIIYOURSELF_VERSION_BETA // not defined for non-beta releases -#define WIIYOURSELF_VERSION_STR _T("1.15") +#define WIIYOURSELF_VERSION_MAJOR 1 +#define WIIYOURSELF_VERSION_MINOR1 1 +#define WIIYOURSELF_VERSION_MINOR2 5 +//#define WIIYOURSELF_VERSION_BETA // not defined for non-beta releases +#define WIIYOURSELF_VERSION_STR _T("1.15") // array sizes -#define TOTAL_BUTTON_BITS 16 // Number of bits for (Classic)ButtonNameFromBit[] -#define TOTAL_FREQUENCIES 10 // Number of frequencies (see speaker_freq[]) +#define TOTAL_BUTTON_BITS 16 // Number of bits for (Classic)ButtonNameFromBit[] +#define TOTAL_FREQUENCIES 10 // Number of frequencies (see speaker_freq[]) // clarity typedef HANDLE EVENT; // state data changes can be signalled to the app via a callback. Set the wiimote // object's 'ChangedCallback' any time to enable them, or alternatively inherit // from the wiimote object and override the ChangedNotifier() virtual method. // of flags indicating which state has changed since the last callback. -typedef void (*state_changed_callback) (class wiimote &owner, - state_change_flags changed, - const wiimote_state &new_state); +typedef void (*state_changed_callback) (class wiimote &owner, + state_change_flags changed, + const wiimote_state &new_state); // internals typedef BOOLEAN (__stdcall *hidwrite_ptr)(HANDLE HidDeviceObject, - PVOID ReportBuffer, - ULONG ReportBufferLength); + PVOID ReportBuffer, + ULONG ReportBufferLength); // (global due to Python wrapper) struct wiimote_state_event { - DWORD time_ms; // system timestamp in milliseconds - wiimote_state state; - }; + DWORD time_ms; // system timestamp in milliseconds + wiimote_state state; + }; // wiimote class - connects and manages a wiimote and its optional extensions // (Nunchuk/Classic Controller), and exposes their state class wiimote : public wiimote_state - { - public: - wiimote (); - virtual ~wiimote (); - - public: - // these can be used to identify Connect()ed wiimote objects (if both - // are unconnected they will pass the compare as their handles are invalid) - inline bool operator == (const wiimote& remote) - { return Handle == remote.Handle; } - inline bool operator != (const wiimote& remote) - { return Handle != remote.Handle; } - - // wiimote data input mode (use with SetReportType()) - // (only enable what you need to save battery power) - enum input_report - { - // combinations if buttons/acceleration/IR/Extension data - IN_BUTTONS = 0x30, - IN_BUTTONS_ACCEL = 0x31, - IN_BUTTONS_ACCEL_IR = 0x33, // reports IR EXTENDED data (dot sizes) - IN_BUTTONS_ACCEL_EXT = 0x35, - IN_BUTTONS_ACCEL_IR_EXT = 0x37, // reports IR BASIC data (no dot sizes) - IN_BUTTONS_BALANCE_BOARD = 0x32, // must use this for the balance board - }; - // string versions - static const TCHAR* ReportTypeName []; - - - public: // convenience accessors: - inline bool IsConnected () const { return bStatusReceived; } - // if IsConnected() unexpectedly returns false, connection was probably lost - inline bool ConnectionLost () const { return bConnectionLost; } - inline bool IsBalanceBoard () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::BALANCE_BOARD)); } - inline bool NunchukConnected () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::NUNCHUK)); } - inline bool ClassicConnected () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::CLASSIC)); } - inline bool MotionPlusConnected () const { return bMotionPlusDetected; } - inline bool MotionPlusEnabled () const { return bMotionPlusEnabled; } - inline bool MotionPlusHasExtension() const { return bMotionPlusExtension; } - inline bool IsPlayingAudio () const { return (Internal.Speaker.Freq && - Internal.Speaker.Volume); } - inline bool IsPlayingSample () const { return IsPlayingAudio() && - (CurrentSample != NULL); } - inline bool IsUsingHIDwrites () const { return bUseHIDwrite; } - inline bool IsRecordingState () const { return Recording.bEnabled; } - - static inline unsigned TotalConnected() { return _TotalConnected; } - - - public: // data - QWORD UniqueID; // constructed from device-specific calibration info. - // Note this is not guaranteed to be truly unique - // as several devices may contain the same calibration - // vluaes - but unique amongst a small number of - // devices. + { + public: + wiimote (); + virtual ~wiimote (); + + public: + // these can be used to identify Connect()ed wiimote objects (if both + // are unconnected they will pass the compare as their handles are invalid) + inline bool operator == (const wiimote& remote) + { return Handle == remote.Handle; } + inline bool operator != (const wiimote& remote) + { return Handle != remote.Handle; } + + // wiimote data input mode (use with SetReportType()) + // (only enable what you need to save battery power) + enum input_report + { + // combinations if buttons/acceleration/IR/Extension data + IN_BUTTONS = 0x30, + IN_BUTTONS_ACCEL = 0x31, + IN_BUTTONS_ACCEL_IR = 0x33, // reports IR EXTENDED data (dot sizes) + IN_BUTTONS_ACCEL_EXT = 0x35, + IN_BUTTONS_ACCEL_IR_EXT = 0x37, // reports IR BASIC data (no dot sizes) + IN_BUTTONS_BALANCE_BOARD = 0x32, // must use this for the balance board + }; + // string versions + static const TCHAR* ReportTypeName []; + + + public: // convenience accessors: + inline bool IsConnected () const { return bStatusReceived; } + // if IsConnected() unexpectedly returns false, connection was probably lost + inline bool ConnectionLost () const { return bConnectionLost; } + inline bool IsBalanceBoard () const { return (Internal.bExtension && + (Internal.ExtensionType==wiimote_state::BALANCE_BOARD)); } + inline bool NunchukConnected () const { return (Internal.bExtension && + (Internal.ExtensionType==wiimote_state::NUNCHUK)); } + inline bool ClassicConnected () const { return (Internal.bExtension && + (Internal.ExtensionType==wiimote_state::CLASSIC)); } + inline bool MotionPlusConnected () const { return bMotionPlusDetected; } + inline bool MotionPlusEnabled () const { return bMotionPlusEnabled; } + inline bool MotionPlusHasExtension() const { return bMotionPlusExtension; } + inline bool IsPlayingAudio () const { return (Internal.Speaker.Freq && + Internal.Speaker.Volume); } + inline bool IsPlayingSample () const { return IsPlayingAudio() && + (CurrentSample != NULL); } + inline bool IsUsingHIDwrites () const { return bUseHIDwrite; } + inline bool IsRecordingState () const { return Recording.bEnabled; } + + static inline unsigned TotalConnected() { return _TotalConnected; } + + + public: // data + QWORD UniqueID; // constructed from device-specific calibration info. + // Note this is not guaranteed to be truly unique + // as several devices may contain the same calibration + // vluaes - but unique amongst a small number of + // devices. #ifdef ID2_FROM_DEVICEPATH - QWORD UniqueID2; // (low-reliabilty, left for reference) - // constructed from the 'device path' string (as - // reported by the OS/stack). This is hopefully - // unique as long as the devices remain installed - // (or at least paired). + QWORD UniqueID2; // (low-reliabilty, left for reference) + // constructed from the 'device path' string (as + // reported by the OS/stack). This is hopefully + // unique as long as the devices remain installed + // (or at least paired). #endif - // optional callbacks - set these to your own fuctions (if required) - state_changed_callback ChangedCallback; - // you can avoid unnecessary callback overhead by specifying a mask - // of which state changes should trigger them (default is any) - state_change_flags CallbackTriggerFlags; - // alternatively, inherit from this class and override this virtual function: - virtual void ChangedNotifier (state_change_flags changed, - const wiimote_state &new_state) {}; - - // get the button name from its bit index (some bits are unused) - static const TCHAR* ButtonNameFromBit [TOTAL_BUTTON_BITS]; - static const TCHAR* GetButtonNameFromBit (unsigned index) - { - _ASSERT(index < TOTAL_BUTTON_BITS); - if(index >= TOTAL_BUTTON_BITS) - return _T("[invalid index]"); - return ButtonNameFromBit[index]; - } - - // same for the Classic Controller - static const TCHAR* ClassicButtonNameFromBit [TOTAL_BUTTON_BITS]; - static const TCHAR* GetClassicButtonNameFromBit (unsigned index) - { - _ASSERT(index < TOTAL_BUTTON_BITS); - if(index >= TOTAL_BUTTON_BITS) - return _T("[invalid index]"); - return ClassicButtonNameFromBit[index]; - } - - // get the frequency from speaker_freq enum - static const unsigned FreqLookup [TOTAL_FREQUENCIES]; - static const unsigned GetFreqLookup (unsigned index) - { - _ASSERT(index < TOTAL_FREQUENCIES); - if(index >= TOTAL_FREQUENCIES) - return 0; - return FreqLookup[index]; - } - - public: // methods - // call Connect() first - returns true if wiimote was found & enabled - // - 'wiimote_index' specifies which *installed* (not necessarily - // *connected*) wiimote should be tried (1 = first, 2 = 2nd etc). - // if you just want the first *available* wiimote that isn't already - // in use, pass in FIRST_AVAILABLE (default). - // - 'force_hidwrites' forces HID output method (it's auto-selected - // when needed and less efficient, so only force for testing). - static const unsigned FIRST_AVAILABLE = 0xffffffff; - bool Connect (unsigned wiimote_index = FIRST_AVAILABLE, - bool force_hidwrites = false); - // disconnect from the controller and stop reading data from it - void Disconnect (); - // set wiimote reporting mode (call after Connnect()) - // continous = true forces the wiimote to send constant updates, even when - // nothing has changed. - // = false only sends data when something has changed (note that - // acceleration data will cause frequent updates anyway as it - // jitters even when the wiimote is stationary) - void SetReportType (input_report type, bool continuous = false); - - // toggle the MotionPlus extension. Call MotionPlusDetected() first to - // see if it's attached. Unlike normal extensions, the MotionPlus does - // not report itself as one until enabled. Once done, it then replaces - // any standard extension attached to it, so be sure to disable it - // if you want to read those (it's not currently known of both can - // be read simultaneously). - bool EnableMotionPlus (); - bool DisableMotionPlus (); - - // this is used to remove unwanted 'at rest' offsets, currently only from - // the Balance Board. make sure there is no weight on the board before - // calling this. it reads the current sensor values and then removes them - // offsets from all subsequent KG and LB state values (the 'raw' values - // are never modified). - void CalibrateAtRest (); - // NOTE: the library automatically calls this when the first weight values - // come in after Connect()ion, but if the device wasn't at rest at - // the time the app can call it again later. - - // to read the state via polling (reading the public state data direct from - // the wiimote object) you must call RefreshState() at the top of every pass. - // returns a combination of flags to indicate which state (if any) has - // changed since the last call. - state_change_flags RefreshState (); - - // reset the wiimote (changes report type to non-continuous buttons-only, - // clears LEDs & rumble, mutes & disables speaker) - void Reset (); - // set/clear the wiimote LEDs - void SetLEDs (BYTE led_bits); // bits 0-3 are valid - // set/clear rumble - void SetRumble (bool on); - // alternative - rumble for a fixed amount of time (asynchronous) - void RumbleForAsync (unsigned milliseconds); - - // *experimental* speaker support: - bool MuteSpeaker (bool on); - bool EnableSpeaker (bool on); - bool PlaySquareWave (speaker_freq freq, BYTE volume = 0x40); - // note: PlaySample currently streams from the passed-in wiimote_sample - - // don't delete it until playback has stopped. - bool PlaySample (const wiimote_sample &sample, - BYTE volume = 0x40, - speaker_freq freq_override = FREQ_NONE); - - // 16bit mono sample loading/conversion to native format: - // .wav sample - static bool Load16bitMonoSampleWAV (const TCHAR* filepath, - wiimote_sample &out); - // raw 16bit mono audio data (can be signed or unsigned) - static bool Load16BitMonoSampleRAW (const TCHAR* filepath, - bool _signed, - speaker_freq freq, - wiimote_sample &out); - // converts a 16bit mono sample array to a wiimote_sample - static bool Convert16bitMonoSamples (const short* samples, - bool _signed, - DWORD length, - speaker_freq freq, - wiimote_sample &out); - - // state recording - records state snapshots to a 'state_history' supplied - // by the caller. states are timestamped and only added - // to the list when the specified state changes. + // optional callbacks - set these to your own fuctions (if required) + state_changed_callback ChangedCallback; + // you can avoid unnecessary callback overhead by specifying a mask + // of which state changes should trigger them (default is any) + state_change_flags CallbackTriggerFlags; + // alternatively, inherit from this class and override this virtual function: + virtual void ChangedNotifier (state_change_flags changed, + const wiimote_state &new_state) {}; + + // get the button name from its bit index (some bits are unused) + static const TCHAR* ButtonNameFromBit [TOTAL_BUTTON_BITS]; + static const TCHAR* GetButtonNameFromBit (unsigned index) + { + _ASSERT(index < TOTAL_BUTTON_BITS); + if(index >= TOTAL_BUTTON_BITS) + return _T("[invalid index]"); + return ButtonNameFromBit[index]; + } + + // same for the Classic Controller + static const TCHAR* ClassicButtonNameFromBit [TOTAL_BUTTON_BITS]; + static const TCHAR* GetClassicButtonNameFromBit (unsigned index) + { + _ASSERT(index < TOTAL_BUTTON_BITS); + if(index >= TOTAL_BUTTON_BITS) + return _T("[invalid index]"); + return ClassicButtonNameFromBit[index]; + } + + // get the frequency from speaker_freq enum + static const unsigned FreqLookup [TOTAL_FREQUENCIES]; + static const unsigned GetFreqLookup (unsigned index) + { + _ASSERT(index < TOTAL_FREQUENCIES); + if(index >= TOTAL_FREQUENCIES) + return 0; + return FreqLookup[index]; + } + + public: // methods + // call Connect() first - returns true if wiimote was found & enabled + // - 'wiimote_index' specifies which *installed* (not necessarily + // *connected*) wiimote should be tried (1 = first, 2 = 2nd etc). + // if you just want the first *available* wiimote that isn't already + // in use, pass in FIRST_AVAILABLE (default). + // - 'force_hidwrites' forces HID output method (it's auto-selected + // when needed and less efficient, so only force for testing). + static const unsigned FIRST_AVAILABLE = 0xffffffff; + bool Connect (unsigned wiimote_index = FIRST_AVAILABLE, + bool force_hidwrites = false); + // disconnect from the controller and stop reading data from it + void Disconnect (); + // set wiimote reporting mode (call after Connnect()) + // continous = true forces the wiimote to send constant updates, even when + // nothing has changed. + // = false only sends data when something has changed (note that + // acceleration data will cause frequent updates anyway as it + // jitters even when the wiimote is stationary) + void SetReportType (input_report type, bool continuous = false); + + // toggle the MotionPlus extension. Call MotionPlusDetected() first to + // see if it's attached. Unlike normal extensions, the MotionPlus does + // not report itself as one until enabled. Once done, it then replaces + // any standard extension attached to it, so be sure to disable it + // if you want to read those (it's not currently known of both can + // be read simultaneously). + bool EnableMotionPlus (); + bool DisableMotionPlus (); + + // this is used to remove unwanted 'at rest' offsets, currently only from + // the Balance Board. make sure there is no weight on the board before + // calling this. it reads the current sensor values and then removes them + // offsets from all subsequent KG and LB state values (the 'raw' values + // are never modified). + void CalibrateAtRest (); + // NOTE: the library automatically calls this when the first weight values + // come in after Connect()ion, but if the device wasn't at rest at + // the time the app can call it again later. + + // to read the state via polling (reading the public state data direct from + // the wiimote object) you must call RefreshState() at the top of every pass. + // returns a combination of flags to indicate which state (if any) has + // changed since the last call. + state_change_flags RefreshState (); + + // reset the wiimote (changes report type to non-continuous buttons-only, + // clears LEDs & rumble, mutes & disables speaker) + void Reset (); + // set/clear the wiimote LEDs + void SetLEDs (BYTE led_bits); // bits 0-3 are valid + // set/clear rumble + void SetRumble (bool on); + // alternative - rumble for a fixed amount of time (asynchronous) + void RumbleForAsync (unsigned milliseconds); + + // *experimental* speaker support: + bool MuteSpeaker (bool on); + bool EnableSpeaker (bool on); + bool PlaySquareWave (speaker_freq freq, BYTE volume = 0x40); + // note: PlaySample currently streams from the passed-in wiimote_sample - + // don't delete it until playback has stopped. + bool PlaySample (const wiimote_sample &sample, + BYTE volume = 0x40, + speaker_freq freq_override = FREQ_NONE); + + // 16bit mono sample loading/conversion to native format: + // .wav sample + static bool Load16bitMonoSampleWAV (const TCHAR* filepath, + wiimote_sample &out); + // raw 16bit mono audio data (can be signed or unsigned) + static bool Load16BitMonoSampleRAW (const TCHAR* filepath, + bool _signed, + speaker_freq freq, + wiimote_sample &out); + // converts a 16bit mono sample array to a wiimote_sample + static bool Convert16bitMonoSamples (const short* samples, + bool _signed, + DWORD length, + speaker_freq freq, + wiimote_sample &out); + + // state recording - records state snapshots to a 'state_history' supplied + // by the caller. states are timestamped and only added + // to the list when the specified state changes. #ifndef SWIG // !Python Wrapper - typedef wiimote_state_event state_event; + typedef wiimote_state_event state_event; #endif - typedef std::list state_history; - static const unsigned UNTIL_STOP = 0xffffffff; - // - pass in a 'state_history' list, and don't destroy/change it until - // recording is stopped. note the list will be cleared first. - // - you can request a specific duration (and use IsRecordingState() to detect - // the end), or UNTIL_STOP. StopRecording() can be called either way. - // - you can use 'change trigger' to specify specific state changes that will - // trigger an insert into the history (others are then ignored). - void RecordState (state_history &events_out, - unsigned max_time_ms = UNTIL_STOP, - state_change_flags change_trigger = CHANGED_ALL); - void StopRecording (); - - - private: // methods - // start reading asynchronously from the controller - bool BeginAsyncRead (); - // request status update (battery level, extension status etc) - void RequestStatusReport (); - // read address or register from Wiimote asynchronously (the result is - // parsed internally whenever it arrives) - bool ReadAddress (int address, short size); - // write a single BYTE to a wiimote address or register - inline void WriteData (int address, BYTE data) { WriteData(address, 1, &data); } - // write a BYTE array to a wiimote address or register - void WriteData (int address, BYTE size, const BYTE* buff); - // callback when data is ready to be processed - void OnReadData (DWORD bytes_read); - // parse individual reports by type - int ParseInput (BYTE* buff); - // detects if MotionPlus is attached (it doesn't report as a normal - // extesnion until it is enabled) - void DetectMotionPlusExtensionAsync (); - // initializes an extension when plugged in. - void InitializeExtension (); - // parses a status report - int ParseStatus (BYTE* buff); - // parses the buttons - int ParseButtons (BYTE* buff); - // parses accelerometer data - int ParseAccel (BYTE* buff); - bool EstimateOrientationFrom(wiimote_state::acceleration &accel); - void ApplyJoystickDeadZones (wiimote_state::joystick &joy); - // parses IR data from report - int ParseIR (BYTE* buff); - // parses data from an extension. - int ParseExtension (BYTE* buff, unsigned offset); - // parses data returned from a read report - int ParseReadAddress (BYTE* buff); - // reads calibration information stored on Wiimote - void ReadCalibration (); - float GetBalanceValue(short sensor, short min, short mid, short max); - // turns on the IR sensor (the mode must match the reporting mode caps) - void EnableIR (wiimote_state::ir::mode mode); - // disables the IR sensor - void DisableIR (); - // writes a report to the Wiimote (NULL = use 'WriteBuff') - bool WriteReport (BYTE* buff); - bool StartSampleThread (); - // returns the rumble BYTE that needs to be sent with reports. - inline BYTE GetRumbleBit () const { return Internal.bRumble? 0x01 : 0x00; } - - // static thread funcs: - static unsigned __stdcall ReadParseThreadfunc (void* param); - static unsigned __stdcall AsyncRumbleThreadfunc (void* param); - static unsigned __stdcall SampleStreamThreadfunc(void* param); - static unsigned __stdcall HIDwriteThreadfunc (void* param); - - private: // data - // wiimote output comands - enum output_report - { - OUT_NONE = 0x00, - OUT_LEDs = 0x11, - OUT_TYPE = 0x12, - OUT_IR = 0x13, - OUT_SPEAKER_ENABLE = 0x14, - OUT_STATUS = 0x15, - OUT_WRITEMEMORY = 0x16, - OUT_READMEMORY = 0x17, - OUT_SPEAKER_DATA = 0x18, - OUT_SPEAKER_MUTE = 0x19, - OUT_IR2 = 0x1a, - }; - // input reports used only internally: - static const int IN_STATUS = 0x20; - static const int IN_READADDRESS = 0x21; - // wiimote device IDs: - static const int VID = 0x057e; // 'Nintendo' - static const int PID = 0x0306; // 'Wiimote' - // we could find this out the hard way using HID, but it's 22 - static const int REPORT_LENGTH = 22; - // wiimote registers - static const int REGISTER_CALIBRATION = 0x0016; - static const int REGISTER_IR = 0x4b00030; - static const int REGISTER_IR_SENSITIVITY_1 = 0x4b00000; - static const int REGISTER_IR_SENSITIVITY_2 = 0x4b0001a; - static const int REGISTER_IR_MODE = 0x4b00033; - static const int REGISTER_EXTENSION_INIT1 = 0x4a400f0; - static const int REGISTER_EXTENSION_INIT2 = 0x4a400fb; - static const int REGISTER_EXTENSION_TYPE = 0x4a400fa; - static const int REGISTER_EXTENSION_CALIBRATION = 0x4a40020; - static const int REGISTER_BALANCE_CALIBRATION = 0x4a40024; - static const int REGISTER_MOTIONPLUS_DETECT = 0x4a600fa; - static const int REGISTER_MOTIONPLUS_INIT = 0x4a600f0; - static const int REGISTER_MOTIONPLUS_ENABLE = 0x4a600fe; - - HANDLE Handle; // read/write device handle - OVERLAPPED Overlapped; // for async Read/WriteFile() IO - HANDLE ReadParseThread; // waits for overlapped reads & parses result - EVENT DataRead; // signals overlapped read complete - bool bUseHIDwrite; // alternative write method (less efficient - // but required for some BT stacks (eg. MS') - // HidD_SetOutputReport is only supported from XP onwards, so detect & - // load it dynamically: - static HMODULE HidDLL; - static hidwrite_ptr _HidD_SetOutputReport; - - volatile bool bStatusReceived; // for output method detection - volatile bool bConnectInProgress; // don't handle extensions until complete - volatile bool bInitInProgress; // stop regular requests until complete - volatile bool bEnablingMotionPlus; // for special init codepath - volatile bool bConnectionLost; // auto-Disconnect()s if set -volatile int MotionPlusDetectCount; // waiting for the result - volatile bool bMotionPlusDetected; - volatile bool bMotionPlusEnabled; - volatile bool bMotionPlusExtension;// detected one plugged into MotionPlus - volatile bool bCalibrateAtRest; // as soon as the first sensor values // come in after a Connect() call. - static unsigned _TotalCreated; - static unsigned _TotalConnected; - input_report ReportType; // type of data the wiimote delivers - // read buffer - BYTE ReadBuff [REPORT_LENGTH]; - // for polling: state is updated on a thread internally, and made only - // made public via RefreshState() - CRITICAL_SECTION StateLock; - wiimote_state Internal; - state_change_flags InternalChanged; // state changes since last RefreshState() - // periodic status report requests (for battery level and connection loss - // detection) - DWORD NextStatusTime; - DWORD NextMPlusDetectTime;// gap between motion plus detections - DWORD MPlusDetectCount; // # of detection tries in quick succesion - // async Hidd_WriteReport() thread - HANDLE HIDwriteThread; + typedef std::list state_history; + static const unsigned UNTIL_STOP = 0xffffffff; + // - pass in a 'state_history' list, and don't destroy/change it until + // recording is stopped. note the list will be cleared first. + // - you can request a specific duration (and use IsRecordingState() to detect + // the end), or UNTIL_STOP. StopRecording() can be called either way. + // - you can use 'change trigger' to specify specific state changes that will + // trigger an insert into the history (others are then ignored). + void RecordState (state_history &events_out, + unsigned max_time_ms = UNTIL_STOP, + state_change_flags change_trigger = CHANGED_ALL); + void StopRecording (); + + + private: // methods + // start reading asynchronously from the controller + bool BeginAsyncRead (); + // request status update (battery level, extension status etc) + void RequestStatusReport (); + // read address or register from Wiimote asynchronously (the result is + // parsed internally whenever it arrives) + bool ReadAddress (int address, short size); + // write a single BYTE to a wiimote address or register + inline void WriteData (int address, BYTE data) { WriteData(address, 1, &data); } + // write a BYTE array to a wiimote address or register + void WriteData (int address, BYTE size, const BYTE* buff); + // callback when data is ready to be processed + void OnReadData (DWORD bytes_read); + // parse individual reports by type + int ParseInput (BYTE* buff); + // detects if MotionPlus is attached (it doesn't report as a normal + // extesnion until it is enabled) + void DetectMotionPlusExtensionAsync (); + // initializes an extension when plugged in. + void InitializeExtension (); + // parses a status report + int ParseStatus (BYTE* buff); + // parses the buttons + int ParseButtons (BYTE* buff); + // parses accelerometer data + int ParseAccel (BYTE* buff); + bool EstimateOrientationFrom(wiimote_state::acceleration &accel); + void ApplyJoystickDeadZones (wiimote_state::joystick &joy); + // parses IR data from report + int ParseIR (BYTE* buff); + // parses data from an extension. + int ParseExtension (BYTE* buff, unsigned offset); + // parses data returned from a read report + int ParseReadAddress (BYTE* buff); + // reads calibration information stored on Wiimote + void ReadCalibration (); + float GetBalanceValue(short sensor, short min, short mid, short max); + // turns on the IR sensor (the mode must match the reporting mode caps) + void EnableIR (wiimote_state::ir::mode mode); + // disables the IR sensor + void DisableIR (); + // writes a report to the Wiimote (NULL = use 'WriteBuff') + bool WriteReport (BYTE* buff); + bool StartSampleThread (); + // returns the rumble BYTE that needs to be sent with reports. + inline BYTE GetRumbleBit () const { return Internal.bRumble? 0x01 : 0x00; } + + // static thread funcs: + static unsigned __stdcall ReadParseThreadfunc (void* param); + static unsigned __stdcall AsyncRumbleThreadfunc (void* param); + static unsigned __stdcall SampleStreamThreadfunc(void* param); + static unsigned __stdcall HIDwriteThreadfunc (void* param); + + private: // data + // wiimote output comands + enum output_report + { + OUT_NONE = 0x00, + OUT_LEDs = 0x11, + OUT_TYPE = 0x12, + OUT_IR = 0x13, + OUT_SPEAKER_ENABLE = 0x14, + OUT_STATUS = 0x15, + OUT_WRITEMEMORY = 0x16, + OUT_READMEMORY = 0x17, + OUT_SPEAKER_DATA = 0x18, + OUT_SPEAKER_MUTE = 0x19, + OUT_IR2 = 0x1a, + }; + // input reports used only internally: + static const int IN_STATUS = 0x20; + static const int IN_READADDRESS = 0x21; + // wiimote device IDs: + static const int VID = 0x057e; // 'Nintendo' + static const int PID = 0x0306; // 'Wiimote' + // we could find this out the hard way using HID, but it's 22 + static const int REPORT_LENGTH = 22; + // wiimote registers + static const int REGISTER_CALIBRATION = 0x0016; + static const int REGISTER_IR = 0x4b00030; + static const int REGISTER_IR_SENSITIVITY_1 = 0x4b00000; + static const int REGISTER_IR_SENSITIVITY_2 = 0x4b0001a; + static const int REGISTER_IR_MODE = 0x4b00033; + static const int REGISTER_EXTENSION_INIT1 = 0x4a400f0; + static const int REGISTER_EXTENSION_INIT2 = 0x4a400fb; + static const int REGISTER_EXTENSION_TYPE = 0x4a400fa; + static const int REGISTER_EXTENSION_CALIBRATION = 0x4a40020; + static const int REGISTER_BALANCE_CALIBRATION = 0x4a40024; + static const int REGISTER_MOTIONPLUS_DETECT = 0x4a600fa; + static const int REGISTER_MOTIONPLUS_INIT = 0x4a600f0; + static const int REGISTER_MOTIONPLUS_ENABLE = 0x4a600fe; + + HANDLE Handle; // read/write device handle + OVERLAPPED Overlapped; // for async Read/WriteFile() IO + HANDLE ReadParseThread; // waits for overlapped reads & parses result + EVENT DataRead; // signals overlapped read complete + bool bUseHIDwrite; // alternative write method (less efficient + // but required for some BT stacks (eg. MS') + // HidD_SetOutputReport is only supported from XP onwards, so detect & + // load it dynamically: + static HMODULE HidDLL; + static hidwrite_ptr _HidD_SetOutputReport; + + volatile bool bStatusReceived; // for output method detection + volatile bool bConnectInProgress; // don't handle extensions until complete + volatile bool bInitInProgress; // stop regular requests until complete + volatile bool bEnablingMotionPlus; // for special init codepath + volatile bool bConnectionLost; // auto-Disconnect()s if set +volatile int MotionPlusDetectCount; // waiting for the result + volatile bool bMotionPlusDetected; + volatile bool bMotionPlusEnabled; + volatile bool bMotionPlusExtension;// detected one plugged into MotionPlus + volatile bool bCalibrateAtRest; // as soon as the first sensor values // come in after a Connect() call. + static unsigned _TotalCreated; + static unsigned _TotalConnected; + input_report ReportType; // type of data the wiimote delivers + // read buffer + BYTE ReadBuff [REPORT_LENGTH]; + // for polling: state is updated on a thread internally, and made only + // made public via RefreshState() + CRITICAL_SECTION StateLock; + wiimote_state Internal; + state_change_flags InternalChanged; // state changes since last RefreshState() + // periodic status report requests (for battery level and connection loss + // detection) + DWORD NextStatusTime; + DWORD NextMPlusDetectTime;// gap between motion plus detections + DWORD MPlusDetectCount; // # of detection tries in quick succesion + // async Hidd_WriteReport() thread + HANDLE HIDwriteThread; #ifdef USE_DYNAMIC_HIDQUEUE - std::queue HIDwriteQueue; + std::queue HIDwriteQueue; #else - // fixed-size queue (to eliminate glitches caused by frequent dynamic memory - // allocations) - struct hid - { - hid () : Queue(NULL), ReadIndex(0), WriteIndex(0) {} - - // Increase the static queue size if you get ASSERTs signalling an - // overflow (too many reports queued up before being sent by the write - // thread). These asserts are harmless though if caused as a result of - // loosing the wiimote connection (eg. battery runs out, or wiimote is - // unpaired by holding the power button). - // Note: MAX_QUEUE_ENTRIES _must_ be a power-of-2, as it - // uses index wraparound optimisations. - static const unsigned MAX_QUEUE_ENTRIES = 1<<7; - - inline bool IsEmpty() const { return (ReadIndex == WriteIndex); } - - bool Allocate () { // allocate memory (only when needed) - _ASSERT(!Queue); if(Queue) return true; - ReadIndex = WriteIndex = 0; - Queue = new queue_entry[MAX_QUEUE_ENTRIES]; - _ASSERT(Queue); return (Queue != NULL); - } - void Deallocate () { - if(!Queue) return; - delete[] Queue; Queue = NULL; - ReadIndex = WriteIndex = 0; - } - - struct queue_entry - { - queue_entry() { memset(Report, 0, sizeof(Report)); } - - BYTE Report [REPORT_LENGTH]; - } *Queue; - - unsigned ReadIndex, WriteIndex; - } HID; + // fixed-size queue (to eliminate glitches caused by frequent dynamic memory + // allocations) + struct hid + { + hid () : Queue(NULL), ReadIndex(0), WriteIndex(0) {} + + // Increase the static queue size if you get ASSERTs signalling an + // overflow (too many reports queued up before being sent by the write + // thread). These asserts are harmless though if caused as a result of + // loosing the wiimote connection (eg. battery runs out, or wiimote is + // unpaired by holding the power button). + // Note: MAX_QUEUE_ENTRIES _must_ be a power-of-2, as it + // uses index wraparound optimisations. + static const unsigned MAX_QUEUE_ENTRIES = 1<<7; + + inline bool IsEmpty() const { return (ReadIndex == WriteIndex); } + + bool Allocate () { // allocate memory (only when needed) + _ASSERT(!Queue); if(Queue) return true; + ReadIndex = WriteIndex = 0; + Queue = new queue_entry[MAX_QUEUE_ENTRIES]; + _ASSERT(Queue); return (Queue != NULL); + } + void Deallocate () { + if(!Queue) return; + delete[] Queue; Queue = NULL; + ReadIndex = WriteIndex = 0; + } + + struct queue_entry + { + queue_entry() { memset(Report, 0, sizeof(Report)); } + + BYTE Report [REPORT_LENGTH]; + } *Queue; + + unsigned ReadIndex, WriteIndex; + } HID; #endif - CRITICAL_SECTION HIDwriteQueueLock; // queue must be locked before being modified - - // async rumble - HANDLE AsyncRumbleThread; // automatically disables rumble if requested - volatile DWORD AsyncRumbleTimeout; - // orientation estimation - unsigned WiimoteNearGUpdates; - unsigned NunchukNearGUpdates; - // audio - HANDLE SampleThread; - const wiimote_sample* volatile CurrentSample; // otherwise playing square wave - // state recording - struct recording - { - volatile bool bEnabled; - state_history *StateHistory; - volatile DWORD StartTimeMS; - volatile DWORD EndTimeMS; // can be UNTIL_STOP - unsigned TriggerFlags; // wiimote changes trigger a state event - unsigned ExtTriggerFlags;// extension changes " - } Recording; - }; + CRITICAL_SECTION HIDwriteQueueLock; // queue must be locked before being modified + + // async rumble + HANDLE AsyncRumbleThread; // automatically disables rumble if requested + volatile DWORD AsyncRumbleTimeout; + // orientation estimation + unsigned WiimoteNearGUpdates; + unsigned NunchukNearGUpdates; + // audio + HANDLE SampleThread; + const wiimote_sample* volatile CurrentSample; // otherwise playing square wave + // state recording + struct recording + { + volatile bool bEnabled; + state_history *StateHistory; + volatile DWORD StartTimeMS; + volatile DWORD EndTimeMS; // can be UNTIL_STOP + unsigned TriggerFlags; // wiimote changes trigger a state event + unsigned ExtTriggerFlags;// extension changes " + } Recording; + }; #endif // _WIIMOTE_H \ No newline at end of file diff --git a/Modules/InputDevices/WiiMote/wiiyourself/wiimote_common.h b/Modules/InputDevices/WiiMote/wiiyourself/wiimote_common.h index c0fd01e1f9..4eb29ed5ca 100644 --- a/Modules/InputDevices/WiiMote/wiiyourself/wiimote_common.h +++ b/Modules/InputDevices/WiiMote/wiiyourself/wiimote_common.h @@ -1,109 +1,124 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ // _______________________________________________________________________________ // -// - WiiYourself! - native C++ Wiimote library v1.15 RC -// (c) gl.tter 2007-9 - http://gl.tter.org +// - WiiYourself! - native C++ Wiimote library v1.15 RC +// (c) gl.tter 2007-9 - http://gl.tter.org // -// see License.txt for conditions of use. see History.txt for change log. +// see License.txt for conditions of use. see History.txt for change log. // _______________________________________________________________________________ // // wiimote_common.h (tab = 4 spaces) // speaker support: enum speaker_freq - { - // (keep in sync with FreqLookup in wiimote.cpp) - FREQ_NONE = 0, - // my PC can't keep up with these using bUseHIDwrite, so I haven't - // been able to tune them yet - FREQ_4200HZ = 1, - FREQ_3920HZ = 2, - FREQ_3640HZ = 3, - FREQ_3360HZ = 4, - // these were tuned until the square-wave was glitch-free on my remote - - // may not be exactly right - FREQ_3130HZ = 5, // +190 - FREQ_2940HZ = 6, // +180 - FREQ_2760HZ = 7, // +150 - FREQ_2610HZ = 8, // +140 - FREQ_2470HZ = 9, - }; + { + // (keep in sync with FreqLookup in wiimote.cpp) + FREQ_NONE = 0, + // my PC can't keep up with these using bUseHIDwrite, so I haven't + // been able to tune them yet + FREQ_4200HZ = 1, + FREQ_3920HZ = 2, + FREQ_3640HZ = 3, + FREQ_3360HZ = 4, + // these were tuned until the square-wave was glitch-free on my remote - + // may not be exactly right + FREQ_3130HZ = 5, // +190 + FREQ_2940HZ = 6, // +180 + FREQ_2760HZ = 7, // +150 + FREQ_2610HZ = 8, // +140 + FREQ_2470HZ = 9, + }; // wiimote_sample - holds the audio sample in the native wiimote format struct wiimote_sample - { - wiimote_sample() : samples(NULL), length(0), freq(FREQ_NONE) {} - BYTE* samples; - DWORD length; - speaker_freq freq; - }; + { + wiimote_sample() : samples(NULL), length(0), freq(FREQ_NONE) {} + BYTE* samples; + DWORD length; + speaker_freq freq; + }; // flags & masks that indicate which part(s) of the wiimote state have changed enum state_change_flags - { - // state didn't change at all - NO_CHANGE = 0, + { + // state didn't change at all + NO_CHANGE = 0, - // Wiimote specific: - CONNECTED = 1<<0, // wiimote just connected - CONNECTION_LOST = 1<<1, - BATTERY_CHANGED = 1<<2, - BATTERY_DRAINED = 1<<3, // close to empty - LEDS_CHANGED = 1<<4, // (probably redudant as wiimmote never - BUTTONS_CHANGED = 1<<5, // changes them unless requested) - ACCEL_CHANGED = 1<<6, - ORIENTATION_CHANGED = 1<<7, - IR_CHANGED = 1<<8, - // all wiimote flags - WIIMOTE_CHANGED = CONNECTION_LOST|BATTERY_CHANGED|BATTERY_DRAINED| - LEDS_CHANGED|BUTTONS_CHANGED|ACCEL_CHANGED| - ORIENTATION_CHANGED|IR_CHANGED, - // - Extensions -: - // Nunchuk: - NUNCHUK_CONNECTED = 1<<9, - NUNCHUK_BUTTONS_CHANGED = 1<<10, - NUNCHUK_ACCEL_CHANGED = 1<<11, - NUNCHUK_ORIENTATION_CHANGED = 1<<12, - NUNCHUK_JOYSTICK_CHANGED = 1<<13, - // all flags - NUNCHUK_CHANGED = NUNCHUK_CONNECTED|NUNCHUK_BUTTONS_CHANGED| - NUNCHUK_ACCEL_CHANGED|NUNCHUK_ORIENTATION_CHANGED| - NUNCHUK_JOYSTICK_CHANGED, - // Classic Controller (inc. Guitars etc): - CLASSIC_CONNECTED = 1<<14, - CLASSIC_BUTTONS_CHANGED = 1<<15, - CLASSIC_JOYSTICK_L_CHANGED = 1<<16, - CLASSIC_JOYSTICK_R_CHANGED = 1<<17, - CLASSIC_TRIGGERS_CHANGED = 1<<18, - // all flags - CLASSIC_CHANGED = CLASSIC_CONNECTED|CLASSIC_BUTTONS_CHANGED| - CLASSIC_JOYSTICK_L_CHANGED| - CLASSIC_JOYSTICK_R_CHANGED| - CLASSIC_TRIGGERS_CHANGED, - // Balance Board: - BALANCE_CONNECTED = 1<<19, - BALANCE_WEIGHT_CHANGED = 1<<20, - // all flags - BALANCE_CHANGED = BALANCE_CONNECTED|BALANCE_WEIGHT_CHANGED, + // Wiimote specific: + CONNECTED = 1<<0, // wiimote just connected + CONNECTION_LOST = 1<<1, + BATTERY_CHANGED = 1<<2, + BATTERY_DRAINED = 1<<3, // close to empty + LEDS_CHANGED = 1<<4, // (probably redudant as wiimmote never + BUTTONS_CHANGED = 1<<5, // changes them unless requested) + ACCEL_CHANGED = 1<<6, + ORIENTATION_CHANGED = 1<<7, + IR_CHANGED = 1<<8, + // all wiimote flags + WIIMOTE_CHANGED = CONNECTION_LOST|BATTERY_CHANGED|BATTERY_DRAINED| + LEDS_CHANGED|BUTTONS_CHANGED|ACCEL_CHANGED| + ORIENTATION_CHANGED|IR_CHANGED, + // - Extensions -: + // Nunchuk: + NUNCHUK_CONNECTED = 1<<9, + NUNCHUK_BUTTONS_CHANGED = 1<<10, + NUNCHUK_ACCEL_CHANGED = 1<<11, + NUNCHUK_ORIENTATION_CHANGED = 1<<12, + NUNCHUK_JOYSTICK_CHANGED = 1<<13, + // all flags + NUNCHUK_CHANGED = NUNCHUK_CONNECTED|NUNCHUK_BUTTONS_CHANGED| + NUNCHUK_ACCEL_CHANGED|NUNCHUK_ORIENTATION_CHANGED| + NUNCHUK_JOYSTICK_CHANGED, + // Classic Controller (inc. Guitars etc): + CLASSIC_CONNECTED = 1<<14, + CLASSIC_BUTTONS_CHANGED = 1<<15, + CLASSIC_JOYSTICK_L_CHANGED = 1<<16, + CLASSIC_JOYSTICK_R_CHANGED = 1<<17, + CLASSIC_TRIGGERS_CHANGED = 1<<18, + // all flags + CLASSIC_CHANGED = CLASSIC_CONNECTED|CLASSIC_BUTTONS_CHANGED| + CLASSIC_JOYSTICK_L_CHANGED| + CLASSIC_JOYSTICK_R_CHANGED| + CLASSIC_TRIGGERS_CHANGED, + // Balance Board: + BALANCE_CONNECTED = 1<<19, + BALANCE_WEIGHT_CHANGED = 1<<20, + // all flags + BALANCE_CHANGED = BALANCE_CONNECTED|BALANCE_WEIGHT_CHANGED, - // Motion Plus - MOTIONPLUS_DETECTED = 1<<21, // attached but not enabled - MOTIONPLUS_ENABLED = 1<<22, - MOTIONPLUS_SPEED_CHANGED = 1<<23, - MOTIONPLUS_EXTENSION_CONNECTED = 1<<24, // an extension is found in the - // MotionPlus port - MOTIONPLUS_EXTENSION_DISCONNECTED = 1<<25, // it was disconnected - // all flags - MOTIONPLUS_CHANGED = MOTIONPLUS_DETECTED|MOTIONPLUS_ENABLED| - MOTIONPLUS_SPEED_CHANGED| - MOTIONPLUS_EXTENSION_CONNECTED| - MOTIONPLUS_EXTENSION_DISCONNECTED, - // General: - EXTENSION_DISCONNECTED = 1<<26, - EXTENSION_PARTIALLY_INSERTED = 1<<27, - EXTENSION_CONNECTED = NUNCHUK_CONNECTED|CLASSIC_CONNECTED| - BALANCE_CONNECTED|MOTIONPLUS_ENABLED, - EXTENSION_CHANGED = EXTENSION_DISCONNECTED|NUNCHUK_CHANGED| - CLASSIC_CHANGED|BALANCE_CHANGED|MOTIONPLUS_CHANGED, - // ALL flags: - CHANGED_ALL = WIIMOTE_CHANGED|EXTENSION_CHANGED, - }; + // Motion Plus + MOTIONPLUS_DETECTED = 1<<21, // attached but not enabled + MOTIONPLUS_ENABLED = 1<<22, + MOTIONPLUS_SPEED_CHANGED = 1<<23, + MOTIONPLUS_EXTENSION_CONNECTED = 1<<24, // an extension is found in the + // MotionPlus port + MOTIONPLUS_EXTENSION_DISCONNECTED = 1<<25, // it was disconnected + // all flags + MOTIONPLUS_CHANGED = MOTIONPLUS_DETECTED|MOTIONPLUS_ENABLED| + MOTIONPLUS_SPEED_CHANGED| + MOTIONPLUS_EXTENSION_CONNECTED| + MOTIONPLUS_EXTENSION_DISCONNECTED, + // General: + EXTENSION_DISCONNECTED = 1<<26, + EXTENSION_PARTIALLY_INSERTED = 1<<27, + EXTENSION_CONNECTED = NUNCHUK_CONNECTED|CLASSIC_CONNECTED| + BALANCE_CONNECTED|MOTIONPLUS_ENABLED, + EXTENSION_CHANGED = EXTENSION_DISCONNECTED|NUNCHUK_CHANGED| + CLASSIC_CHANGED|BALANCE_CHANGED|MOTIONPLUS_CHANGED, + // ALL flags: + CHANGED_ALL = WIIMOTE_CHANGED|EXTENSION_CHANGED, + }; diff --git a/Modules/InputDevices/WiiMote/wiiyourself/wiimote_state.h b/Modules/InputDevices/WiiMote/wiiyourself/wiimote_state.h index e3096a422a..972b8765c0 100644 --- a/Modules/InputDevices/WiiMote/wiiyourself/wiimote_state.h +++ b/Modules/InputDevices/WiiMote/wiiyourself/wiimote_state.h @@ -1,379 +1,394 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ // _______________________________________________________________________________ // // - WiiYourself! - native C++ Wiimote library v1.15 // (c) gl.tter 2007-10 - http://gl.tter.org // // see License.txt for conditions of use. see History.txt for change log. // _______________________________________________________________________________ // // wiimote_state.h (tab = 4 spaces) // the 'wiimote_state' struct contains all the Wiimote and Extension state data // (buttons etc) - the wiimote class inherits from this and the app can poll // the data there at any time. #ifdef _MSC_VER // VC # pragma once #endif #ifndef _WIIMOTE_STATE_H # define _WIIMOTE_STATE_H #include "wiimote_common.h" // wiimote_state (contains the Wiimote and Extension data and settings) struct wiimote_state { friend class wiimote; // for Clear() // calibration information (stored on the Wiimote) struct calibration_info { BYTE X0, Y0, Z0; BYTE XG, YG, ZG; } CalibrationInfo; // button state: struct buttons { // convenience accessors inline bool A () const { return (Bits & _A) != 0; } inline bool B () const { return (Bits & _B) != 0; } inline bool Plus () const { return (Bits & PLUS) != 0; } inline bool Home () const { return (Bits & HOME) != 0; } inline bool Minus () const { return (Bits & MINUS) != 0; } inline bool One () const { return (Bits & ONE) != 0; } inline bool Two () const { return (Bits & TWO) != 0; } inline bool Up () const { return (Bits & UP) != 0; } inline bool Down () const { return (Bits & DOWN) != 0; } inline bool Left () const { return (Bits & LEFT) != 0; } inline bool Right () const { return (Bits & RIGHT) != 0; } // all 11 buttons stored as bits (set = pressed) WORD Bits; // button bit masks (little-endian order) enum mask { LEFT = 0x0001, RIGHT = 0x0002, DOWN = 0x0004, UP = 0x0008, PLUS = 0x0010, TWO = 0x0100, ONE = 0x0200, _B = 0x0400, // ie. trigger _A = 0x0800, MINUS = 0x1000, HOME = 0x8000, // ALL = LEFT|RIGHT|DOWN|UP|PLUS|TWO|ONE|_A|_B|MINUS|HOME, }; } Button; // accelerometers state: struct acceleration { BYTE RawX, RawY, RawZ, RawXLSB, RawYLSB, RawZLSB; float X, Y, Z; // note: experimental! the orientation values can only be safely estimated // if the controller isn't accelerating (otherwise there is no // simple way to seperate orientation from acceleration - except // perhaps using the IR reference and/or some clever assumptions). // so for now the code only updates orientation if the controller // appear to be stationary (by checking if the acceleration vector // length is near 1G for several updates in a row). // also note that there is no way to detect Yaw from the accelerometer // alone when it's pointing at the screen (and I'm not curently // processing IR): struct orientation { float X, Y, Z; unsigned UpdateAge; // how many acceleration updates ago the last // orientation estimate was made (if this // value is high, the values are out-of-date // and probably shouldn't be used). // Euler angle support (useful for some things). // * note that decomposing to Euler angles is complex, not always reliable, // and also depends on your assumptions about the order each component // is applied in. you may need to handle this yourself for more // complex scenarios * float Pitch; // in degrees (-180 - +180) float Roll; // " // float Yaw; } Orientation; } Acceleration; // IR camera state: struct ir { // in theory the IR imager is 1024x768 and so should report raw coords // 0-1023 x 0-767. in practice I have never seen them exceed the values // below, so I'm using them instead to give the full 0-1 float range // (it's possible that the edge pixels are used for processing, or masked // out due to being unreliable). let me know if your wiimote reports // a different range. static const unsigned MAX_RAW_X = 1016; static const unsigned MAX_RAW_Y = 760; // data mode reported by the IR sensor enum mode { OFF = 0x00, BASIC = 0x01, // 10 bytes EXTENDED = 0x03, // 12 bytes FULL = 0x05, // 16 bytes * 2 (format unknown) }; mode Mode; // read-only (depends on ReportType set) struct dot { bool bVisible; // other values are not valid if == false unsigned RawX; unsigned RawY; float X; // 0-1 (left-right) float Y; // " (top -bottom) int Size; // (not available in BASIC mode) } Dot[4]; } IR; struct leds { // all LEDs stored in bits 0-3 (1 = lit) BYTE Bits; // convenience accessors: inline bool Lit (unsigned index) { _ASSERT(index < 4); return (index >= 4)? false : ((Bits & (1<GetImageDescriptor(); // initialize dimension information for (unsigned int i=0; i<8; i++) { picDesc->n[i] = 1; } // set dimension information picDesc->dim = refImg->GetDimension(); memcpy( picDesc->n, imDesc->GetDimensions(), picDesc->dim * sizeof(unsigned int) ); picDesc->type = CastToIpPicType( refImg->GetPixelType().GetTypeId() ); picDesc->bpe = refImg->GetPixelType().GetBpe(); picDesc->data = refImg->GetData(); return picDesc; } mitkIpPicDescriptor* mitk::CastToIpPicDescriptor(itk::SmartPointer refItem, mitkIpPicDescriptor *picDesc) { // initialize dimension information for (unsigned int i=0; i<8; i++) { picDesc->n[i] = 1; } // get the dimensionality information from image item picDesc->dim = refItem->GetDimension(); for( unsigned int i=0; idim; i++) { picDesc->n[i] = refItem->GetDimension(i); } picDesc->type = CastToIpPicType( refItem->GetPixelType().GetTypeId() ); picDesc->bpe = refItem->GetPixelType().GetBpe(); picDesc->data = refItem->GetData(); return picDesc; } mitk::ImageDescriptor::Pointer mitk::CastToImageDescriptor(mitkIpPicDescriptor *desc) { mitk::ImageDescriptor::Pointer imDescriptor = mitk::ImageDescriptor::New(); imDescriptor->Initialize( desc->n, desc->dim ); mitk::PixelType ptype = CastToPixelType( desc->type, (desc->bpe/8) ); imDescriptor->AddNewChannel(ptype, "imported by pic"); return imDescriptor; } mitkIpPicType_t mitk::CastToIpPicType( const std::type_info& intype ) { //const std::type_info& intype = ptype.GetTypeId(); //MITK_INFO << "Casting to PicType from " << intype.name() << std::endl; const bool isSignedIntegralType = ( intype == typeid(int) || intype == typeid(short) || intype == typeid(char) || intype == typeid(long int) ); const bool isUnsignedIntegralType = ( intype == typeid(unsigned int) || intype == typeid(unsigned short) || intype == typeid(unsigned char) || intype == typeid(unsigned long int) ); const bool isFloatingPointType = ( intype == typeid(float) || intype == typeid(double) ); if( isSignedIntegralType ) return mitkIpPicInt; if( isUnsignedIntegralType ) return mitkIpPicUInt; if( isFloatingPointType ) return mitkIpPicFloat; return mitkIpPicUnknown; } mitk::PixelType mitk::CastToPixelType(mitkIpPicType_t pictype, size_t bpe) { const bool isSignedIntegralType = (pictype == mitkIpPicInt ); const bool isUnsignedIntegralType = (pictype == mitkIpPicUInt ); if(isSignedIntegralType) { switch(bpe) { case sizeof(char): return MakeScalarPixelType(); case sizeof(short): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } else if( isUnsignedIntegralType ) { switch(bpe) { case sizeof(unsigned char): return MakeScalarPixelType(); case sizeof(unsigned short): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } else // is floating point type { switch(bpe) { case sizeof(float): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } } diff --git a/Modules/LegacyAdaptors/mitkLegacyAdaptors.h b/Modules/LegacyAdaptors/mitkLegacyAdaptors.h index e13da1dcf9..bbf5554f4e 100644 --- a/Modules/LegacyAdaptors/mitkLegacyAdaptors.h +++ b/Modules/LegacyAdaptors/mitkLegacyAdaptors.h @@ -1,62 +1,77 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _mitkLegacyAdaptors_h #define _mitkLegacyAdaptors_h_ #include "mitkCommon.h" #include "LegacyAdaptorsExports.h" #include #include "mitkImage.h" /** \file mitkLegacyAdaptors.h * * The LegacyAdaptors module is intended to provide an interface to deprecated types/objects/methods as part of backward compatibility * Currently the module offers methods for casting an Image or an ImageDataItem respectively to a mitkIpPicDescriptor object since several Algorigthms * in MITK Modules still use the deprecated IpPic format and algorithms. * * \warning The IpPic-related classes are no more accessible through the Core Module. The dependencies needs to be set directly for the affected module. Furthermore, * if you want to cast information between mitk::Image and mitkIpPicDescriptor, also the dependency to the LegacyAdaptors module needs to be set. */ namespace mitk { /** \brief Constructs a legacy mitkIpPicDescriptor from mitk::Image Meant to support legacy code, which was base on mitkIpPicDescriptor types. Please remind that such code should be migrated towards ITK/VTK solutions. */ LegacyAdaptors_EXPORT mitkIpPicDescriptor* CastToIpPicDescriptor(mitk::Image::Pointer, mitkIpPicDescriptor* picDesc); /** \brief Constructs a legacy mitkIpPicDescriptor form mitk::ImageDataItem \warning The returned IpPicDescriptor is only referencing the memory block with the data managed by the given ImageDataItem parameter. Simply calling ipPicFree( desc ) will delete the data and so will the ImageDataItem try when it get deleted. Simplest way to avoid the duplicate deletion attempt is to set the desc->data manually to NULL before calling the ipPicFree() on the descriptor */ LegacyAdaptors_EXPORT mitkIpPicDescriptor* CastToIpPicDescriptor(itk::SmartPointer, mitkIpPicDescriptor *picDesc ); /** \brief Constructs an ImageDescriptor from legacy mitkIpPicDescriptor Performs the oposite cast direction to \sa CastToIpPicDescriptor */ LegacyAdaptors_EXPORT DEPRECATED(mitk::ImageDescriptor::Pointer CastToImageDescriptor(mitkIpPicDescriptor* desc)); /** \brief Constructs a legacy type information from mitk::PixelType The IpPicDescriptor uses own notations for different pixel types. This casting is needed e.g. by the CastToIpPicDescriptor method. */ LegacyAdaptors_EXPORT DEPRECATED(mitkIpPicType_t CastToIpPicType( const std::type_info& intype ) ); /** \brief Returns a mitk::PixelType object corresponding to given mitkIpPicType_t The method needs the mitkIpPicType_t and the bits per element (bpe) information to be able to create the correct corresponding PixelType \sa PixelType */ LegacyAdaptors_EXPORT DEPRECATED(PixelType CastToPixelType( mitkIpPicType_t pictype, size_t bpe ) ); } // end namespace mitk #endif diff --git a/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.h b/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.h index 84254142b3..50fb578de3 100644 --- a/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.h +++ b/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.h @@ -1,139 +1,154 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkIntelligentBinaryClosingFilter_h #define __itkIntelligentBinaryClosingFilter_h #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include #include #include #include #include #include #include #include #include #include namespace itk { /** \class itkIntelligentBinaryClosingFilter * WARNING: This filtezr needs at least ITK version 3.2 * or above to run and compile!!! * */ template class ITK_EXPORT IntelligentBinaryClosingFilter : public ImageToImageFilter< TInputImage, TOutputImage > { public: /** Standard "Self" typedef. */ typedef IntelligentBinaryClosingFilter Self; /** The type of input image. */ typedef TInputImage InputImageType; /** Dimension of the input and output images. */ itkStaticConstMacro (ImageDimension, unsigned int, TInputImage::ImageDimension); /** The type of output image. */ typedef TOutputImage OutputImageType; /** Standard super class typedef support. */ typedef ImageToImageFilter< InputImageType, OutputImageType > Superclass; /** Smart pointer typedef support */ typedef SmartPointer Pointer; /** Run-time type information (and related methods) */ itkTypeMacro(IntelligentBinaryClosingFilter, ImageToImageFilter); /** Method for creation through the object factory. */ itkNewMacro(Self); /** Standard process object method. This filter is not multithreaded. */ void GenerateData(); /** Overloaded to link the input to this filter with the input of the mini-pipeline */ void SetInput(const InputImageType *input) { // processObject is not const-correct so a const_cast is needed here this->ProcessObject::SetNthInput(0, const_cast( input ) ); - m_DilateImageFilter->SetInput( const_cast( input ) ); + m_DilateImageFilter->SetInput( const_cast( input ) ); } virtual void SetInput( unsigned int i, const TInputImage * image) { if (i != 0) { itkExceptionMacro(<< "Filter has only one input."); } else { this->SetInput(image); } } itkGetMacro( ClosingRadius, float ); itkSetMacro( ClosingRadius, float ); itkGetMacro( SurfaceRatio, float ); itkSetMacro( SurfaceRatio, float ); protected: IntelligentBinaryClosingFilter(); virtual ~IntelligentBinaryClosingFilter() {} IntelligentBinaryClosingFilter(const Self&) {} void operator=(const Self&) {} void PrintSelf(std::ostream& os, Indent indent) const; private: typedef typename InputImageType::PixelType InputPixelType; typedef BinaryBallStructuringElement StructuringElementType; typedef BinaryErodeImageFilter BinaryErodeImageFilterType; typedef BinaryDilateImageFilter BinaryDilateImageFilterType; typedef SubtractImageFilter SubtractImageFilterType; typedef ConnectedComponentImageFilter ConnectedComponentImageFilterType; typedef RelabelComponentImageFilter RelabelComponentImageFilterType; typedef GrayscaleDilateImageFilter DilateComponentImageFilterType; typedef ImageRegionIterator InputIteratorType; typedef ImageRegionConstIterator ConstInputIteratorType; typedef ImageRegionIterator OutputIteratorType; typename BinaryErodeImageFilterType::Pointer m_ErodeImageFilter; typename BinaryDilateImageFilterType::Pointer m_DilateImageFilter; typename SubtractImageFilterType::Pointer m_SubtractImageFilter; typename ConnectedComponentImageFilterType::Pointer m_ConnectedComponentImageFilter; typename RelabelComponentImageFilterType::Pointer m_RelabelComponentImageFilter; typename DilateComponentImageFilterType::Pointer m_BorderDetectionDilateFilter; //typename BinaryDilateImageFilterType::Pointer m_BorderAdjacencyDilateFilter; float m_ClosingRadius; float m_SurfaceRatio; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkIntelligentBinaryClosingFilter.txx" #endif #endif //IntelligentBinaryClosingFilter_h diff --git a/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.txx b/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.txx index 8a121a31ac..590fa80628 100644 --- a/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.txx +++ b/Modules/MitkExt/Algorithms/itkIntelligentBinaryClosingFilter.txx @@ -1,134 +1,149 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _itkIntelligentBinaryClosingFilter_txx #define _itkIntelligentBinaryClosingFilter_txx #include "itkIntelligentBinaryClosingFilter.h" #include namespace itk { template< class TInputImage, class TOutputImage > IntelligentBinaryClosingFilter ::IntelligentBinaryClosingFilter() { m_ErodeImageFilter = BinaryErodeImageFilterType::New(); m_DilateImageFilter = BinaryDilateImageFilterType::New(); m_SubtractImageFilter = SubtractImageFilterType::New(); m_ConnectedComponentImageFilter = ConnectedComponentImageFilterType::New(); m_RelabelComponentImageFilter = RelabelComponentImageFilterType::New(); m_RelabelComponentImageFilter->SetInPlace( true ); m_BorderDetectionDilateFilter = DilateComponentImageFilterType::New(); m_ClosingRadius = 4.0; m_SurfaceRatio = 70; } template< class TInputImage, class TOutputImage > void IntelligentBinaryClosingFilter::GenerateData() { const InputImageType *input = this->GetInput(); // Allocate the output image. typename OutputImageType::Pointer output = this->GetOutput(); output->SetRequestedRegion( input->GetRequestedRegion() ); output->SetBufferedRegion( input->GetBufferedRegion() ); output->SetLargestPossibleRegion( input->GetLargestPossibleRegion() ); output->Allocate(); // set up structuring element for closing StructuringElementType seClosing; unsigned long radius[ImageDimension]; const typename InputImageType::SpacingType spacing = input->GetSpacing(); for (unsigned int d=0; dSetInput( this->GetInput() ); m_DilateImageFilter->SetKernel( seClosing ); m_DilateImageFilter->SetDilateValue( 1 ); m_ErodeImageFilter->SetInput( m_DilateImageFilter->GetOutput() ); m_ErodeImageFilter->SetKernel( seClosing ); m_ErodeImageFilter->SetErodeValue( 1 ); // subtraction m_SubtractImageFilter->SetInput1( m_ErodeImageFilter->GetOutput() ); m_SubtractImageFilter->SetInput2( this->GetInput() ); // connected components m_ConnectedComponentImageFilter->SetInput( m_SubtractImageFilter->GetOutput() ); m_RelabelComponentImageFilter->SetInput( m_ConnectedComponentImageFilter->GetOutput() ); m_RelabelComponentImageFilter->Update(); // set up structuring element for border voxel detection StructuringElementType seBorder; for (unsigned int d=0; dSetInput( m_RelabelComponentImageFilter->GetOutput() ); m_BorderDetectionDilateFilter->SetKernel( seBorder ); m_BorderDetectionDilateFilter->Update(); // count volumes and border voxels for all components OutputIteratorType itComp( m_RelabelComponentImageFilter->GetOutput(), m_RelabelComponentImageFilter->GetOutput()->GetLargestPossibleRegion() ); OutputIteratorType itBorder( m_BorderDetectionDilateFilter->GetOutput(), m_BorderDetectionDilateFilter->GetOutput()->GetLargestPossibleRegion() ); ConstInputIteratorType itIn( input, input->GetLargestPossibleRegion() ); std::vector volume( m_RelabelComponentImageFilter->GetNumberOfObjects()+1, 0 ); std::vector border( m_RelabelComponentImageFilter->GetNumberOfObjects()+1, 0 ); std::vector adjacent( m_RelabelComponentImageFilter->GetNumberOfObjects()+1, 0 ); typename OutputImageType::ValueType borderId, compId; for (itComp.GoToBegin(), itBorder.GoToBegin(), itIn.GoToBegin(); !itComp.IsAtEnd(); ++itComp, ++itBorder, ++itIn ) { borderId = itBorder.Get(); if (borderId != 0) { compId = itComp.Get(); if (compId != 0) { volume[compId]++; } else { // this is border country border[borderId]++; if (itIn.Get() != 0) adjacent[borderId]++; } } } // calculate ratios std::vector ratio( m_RelabelComponentImageFilter->GetNumberOfObjects()+1, 0 ); MITK_INFO << " " << m_RelabelComponentImageFilter->GetNumberOfObjects() << " components found" << std::endl; for (unsigned int i=0; iGetLargestPossibleRegion() ); for (itOut.GoToBegin(), itIn.GoToBegin(), itComp.GoToBegin(); !itOut.IsAtEnd(); ++itOut, ++itIn, ++itComp ) { if (itIn.Get() != 0) { itOut.Set( 1 ); } else { compId = itComp.Get(); if (ratio[compId] > m_SurfaceRatio) itOut.Set( 1 ); else itOut.Set( 0 ); } } } template void IntelligentBinaryClosingFilter::PrintSelf(std::ostream& os, Indent indent) const { Superclass::PrintSelf(os,indent); } } // end namespace itk #endif diff --git a/Modules/MitkExt/Algorithms/mitkvtkImageStencilRaster.h b/Modules/MitkExt/Algorithms/mitkvtkImageStencilRaster.h index 1815d054fa..165937ddaf 100644 --- a/Modules/MitkExt/Algorithms/mitkvtkImageStencilRaster.h +++ b/Modules/MitkExt/Algorithms/mitkvtkImageStencilRaster.h @@ -1,98 +1,113 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkImageStencilData.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkImageStencilData - efficient description of an image stencil // .SECTION Description // vtkImageStencilData describes an image stencil in a manner which is // efficient both in terms of speed and storage space. The stencil extents // are stored for each x-row across the image (multiple extents per row if // necessary) and can be retrieved via the GetNextExtent() method. // .SECTION see also // vtkImageStencilSource vtkImageStencil #ifndef __vtkImageStencilRaster_h #define __vtkImageStencilRaster_h #include "vtkImageStencilData.h" #include "vtkDataObject.h" #include "MitkExtExports.h" //BTX // Description: // This is a helper class for stencil creation. It is a raster with // infinite resolution in the X direction (approximately, since it uses // double precision). Lines that represent polygon edges can be drawn // into this raster, and then filled given a tolerance. class MitkExt_EXPORT vtkImageStencilRaster { public: // Description: // Create a raster with the specified whole y extent. vtkImageStencilRaster(const int wholeExtent[2]); // Description: // Destructor. ~vtkImageStencilRaster(); // Description: // Reset the raster to its original state, but keep the same whole // extent. Pre-allocate the specified 1D allocateExtent, which must be // within the whole extent. void PrepareForNewData(const int allocateExtent[2] = 0); // Description: // Insert a line into the raster, given the two end points. // The "inflect1" and "inflect2" should be set if you want // to add a small vertical tolerance to either endpoints. void InsertLine(const double p1[2], const double p2[2], bool inflect1, bool inflect2); // Description: // Fill the specified extent of a vtkImageStencilData with the raster, // after permuting the raster according to xj and yj. void FillStencilData(vtkImageStencilData *data, const int extent[6], int xj = 0, int yj = 1); // Description: // The tolerance for float-to-int conversions. void SetTolerance(double tol) { this->Tolerance = tol; } double GetTolerance() { return this->Tolerance; } protected: // Description: // Ensure that the raster is initialized for the specified range // of y values, which must be within the Extent. void PrepareExtent(int ymin, int ymax); // Description: // Insert an x point into the raster. If the y value is larger // than the y extent, the extent will grow automatically. void InsertPoint(int y, double x); int Extent[2]; int UsedExtent[2]; double **Raster; double Tolerance; private: vtkImageStencilRaster(const vtkImageStencilRaster&); // Not implemented. void operator=(const vtkImageStencilRaster&); // Not implemented. }; //ETX #endif diff --git a/Modules/MitkExt/Algorithms/mitkvtkLassoStencilSource.h b/Modules/MitkExt/Algorithms/mitkvtkLassoStencilSource.h index 86ada7a3b7..08c54ddc38 100644 --- a/Modules/MitkExt/Algorithms/mitkvtkLassoStencilSource.h +++ b/Modules/MitkExt/Algorithms/mitkvtkLassoStencilSource.h @@ -1,107 +1,122 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: vtkLassoStencilSource.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkLassoStencilSource - Create a stencil from a contour // .SECTION Description // vtkLassoStencilSource will create an image stencil from a // set of points that define a contour. Its output can be // used with vtkImageStecil or other vtk classes that apply // a stencil to an image. // .SECTION See Also // vtkROIStencilSource vtkPolyDataToImageStencil // .SECTION Thanks // Thanks to David Gobbi for contributing this class to VTK. #ifndef __vtkLassoStencilSource_h #define __vtkLassoStencilSource_h #include "vtkImageStencilSource.h" #include "MitkExtExports.h" class vtkPoints; class vtkSpline; class vtkLSSPointMap; class MitkExt_EXPORT vtkLassoStencilSource : public vtkImageStencilSource { public: static vtkLassoStencilSource *New(); vtkTypeMacro(vtkLassoStencilSource, vtkImageStencilSource); void PrintSelf(ostream& os, vtkIndent indent); //BTX enum { POLYGON = 0, SPLINE = 1, }; //ETX // Description: // The shape to use, default is "Polygon". The spline is a // cardinal spline. Bezier splines are not yet supported. vtkGetMacro(Shape, int); vtkSetClampMacro(Shape, int, POLYGON, SPLINE); void SetShapeToPolygon() { this->SetShape(POLYGON); }; void SetShapeToSpline() { this->SetShape(SPLINE); }; virtual const char *GetShapeAsString(); // Description: // The points that make up the lassoo. The loop does not // have to be closed, the last point will automatically be // connected to the first point by a straight line segment. virtual void SetPoints(vtkPoints *points); vtkGetObjectMacro(Points, vtkPoints); // Description: // The slice orientation. The default is 2, which is XY. // Other values are 0, which is YZ, and 1, which is XZ. vtkGetMacro(SliceOrientation, int); vtkSetClampMacro(SliceOrientation, int, 0, 2); // Description: // The points for a particular slice. This will override the // points that were set by calling SetPoints() for the slice. // To clear the setting, call SetSlicePoints(slice, NULL). virtual void SetSlicePoints(int i, vtkPoints *points); virtual vtkPoints *GetSlicePoints(int i); // Description: // Remove points from all slices. virtual void RemoveAllSlicePoints(); // Description: // Overload GetMTime() to include the timestamp on the points. unsigned long GetMTime(); protected: vtkLassoStencilSource(); ~vtkLassoStencilSource(); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); int Shape; int SliceOrientation; vtkPoints *Points; vtkSpline *SplineX; vtkSpline *SplineY; vtkLSSPointMap *PointMap; private: vtkLassoStencilSource(const vtkLassoStencilSource&); // Not implemented. void operator=(const vtkLassoStencilSource&); // Not implemented. }; #endif diff --git a/Modules/MitkExt/DataManagement/mitkObjectObserver.h b/Modules/MitkExt/DataManagement/mitkObjectObserver.h index 5a8f7cb9eb..33fc897140 100644 --- a/Modules/MitkExt/DataManagement/mitkObjectObserver.h +++ b/Modules/MitkExt/DataManagement/mitkObjectObserver.h @@ -1,20 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKOBJECTOBSERVER_H #define MITKOBJECTOBSERVER_H #include #include "mitkSetObserver.h" namespace mitk { /// /// Abstract interface for classes /// that want to be informed when an /// itk object was modified or deleted /// struct ObjectObserver: public SetObserver { }; } #endif // MITKOBJECTOBSERVER_H diff --git a/Modules/MitkExt/DataManagement/mitkObjectSet.cpp b/Modules/MitkExt/DataManagement/mitkObjectSet.cpp index 2384dfc27e..41183bd836 100644 --- a/Modules/MitkExt/DataManagement/mitkObjectSet.cpp +++ b/Modules/MitkExt/DataManagement/mitkObjectSet.cpp @@ -1 +1,16 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkObjectSet.h" diff --git a/Modules/MitkExt/DataManagement/mitkObjectSet.h b/Modules/MitkExt/DataManagement/mitkObjectSet.h index 015c2d6bc5..3ab920d5e1 100644 --- a/Modules/MitkExt/DataManagement/mitkObjectSet.h +++ b/Modules/MitkExt/DataManagement/mitkObjectSet.h @@ -1,11 +1,26 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKObjectSet_H #define MITKObjectSet_H #include namespace mitk { typedef mitk::Set ObjectSet; } #endif // MITKObjectSet_H diff --git a/Modules/MitkExt/DataManagement/mitkSet.h b/Modules/MitkExt/DataManagement/mitkSet.h index cbadd621f2..646a47fd4e 100644 --- a/Modules/MitkExt/DataManagement/mitkSet.h +++ b/Modules/MitkExt/DataManagement/mitkSet.h @@ -1,242 +1,257 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkSet_H #define mitkSet_H #include #include #include #include #include #include "mitkSetObserver.h" namespace mitk { /// /// A class that acts like a weak pointer /// but for a list of itk objects /// template class Set: virtual public itk::Object { public: typedef mitk::SetObserver Observer; mitkClassMacro(Set, itk::Object); itkFactorylessNewMacro(Set); Set() { } /// /// clears this set, copies over all elements from otherSet /// void Copy( mitk::Set* otherSet ) { this->Clear(); for(unsigned int i=0; i< otherSet->GetSize(); ++i) { this->Add( otherSet->Get(i) ); } } bool Add ( const T& obj ) { if(this->Has(obj)) // this is a set! do not add twice return false; // add it now m_Objects.push_back(obj); // if index is not valid any more, just add // the element // subscribe for modified event typename itk::MemberCommand >::Pointer _modifiedCommand = itk::MemberCommand >::New(); _modifiedCommand->SetCallbackFunction(this , &Set::OnObjectModified); m_ObjectModifiedTags[obj] = obj->AddObserver(itk::ModifiedEvent(), _modifiedCommand); // subscribe for delete event typename itk::MemberCommand >::Pointer _DeleteCommand = itk::MemberCommand >::New(); _DeleteCommand->SetCallbackFunction(this , &Set::OnObjectModified); m_ObjectDeleteTags[obj] = obj->AddObserver(itk::DeleteEvent(), _DeleteCommand); for(typename std::set*>::iterator it = m_SetObserver.begin(); it != m_SetObserver.end(); ++it) (*it)->OnAdded(obj); this->Modified(); return true; } bool Remove ( const T& obj ) { return this->Remove(this->IndexOf(obj)); } bool Remove ( int index ) { if( !this->IsValid(index) ) // element must exist to be removed return false; typename std::vector::iterator it = m_Objects.begin(); std::advance(it, index); T& obj = *it; for(typename std::set*>::iterator it2 = m_SetObserver.begin(); it2 != m_SetObserver.end(); ++it2) (*it2)->OnRemove(*it); // remove it now obj->RemoveObserver(m_ObjectModifiedTags[obj]); obj->RemoveObserver(m_ObjectDeleteTags[obj]); m_ObjectModifiedTags.erase(obj); m_ObjectDeleteTags.erase(obj); m_Objects.erase(it); this->Modified(); return true; } void Clear () { while(m_Objects.size() > 0) this->Remove(m_Objects.size()-1); } unsigned int GetSize() const { return m_Objects.size(); } int IndexOf(const T& obj) const { int index = -1; typename std::vector::const_iterator it = m_Objects.begin(); for(unsigned int i=0; iIndexOf(obj) != -1; } bool IsEmpty() const { return m_Objects.empty(); } bool IsValid( int index ) const { if(index >= 0) { return m_Objects.size() > 0 && static_cast< unsigned int > (index) < m_Objects.size(); } return false; } T& Front() { return m_Objects.front(); } T& Back() { return m_Objects.back(); } T& Get( unsigned int index ) { return m_Objects.at(index); } const T& Front() const { return m_Objects.front(); } const T& Back() const { return m_Objects.back(); } const T& Get( unsigned int index ) const { return m_Objects.at(index); } void AddObserver( SetObserver* observer ) const { m_SetObserver.insert( observer ); } void RemoveObserver( SetObserver* observer ) const { m_SetObserver.erase( observer ); } void OnObjectModified(const itk::Object* caller , const itk::EventObject &event) { unsigned int i=0; for(; i(m_Objects.at(i)) == caller ) break; const itk::DeleteEvent* delEvent = dynamic_cast(&event); // inform listeners for(typename std::set*>::iterator it = m_SetObserver.begin(); it != m_SetObserver.end(); ++it) delEvent ? (*it)->OnDelete( this->Get(i) ) : (*it)->OnModified( this->Get(i) ); // remove from list if object was deleted (no dangling pointers) if(delEvent) { this->Remove(i); } } Set(const Set& other) { *this = other; } Set& operator= (const Set& other) { // do not simply copy -> because of observer objects // instead: use add method for each element of the other List for(int i=0; iAdd( other.Get(i) ); return *this; } virtual ~Set() { this->Clear(); } protected: /// /// Holds all objects /// std::vector m_Objects; /// /// holds the list of observed itk objects (will be updated in setat()) /// mutable std::set*> m_SetObserver; /// /// \brief Holds all tags of Modified Event Listeners. /// std::map m_ObjectModifiedTags; /// /// \brief Holds all tags of Modified Event Listeners. /// std::map m_ObjectDeleteTags; }; } // namespace mitk #endif // mitkSet_H diff --git a/Modules/MitkExt/DataManagement/mitkSetObserver.h b/Modules/MitkExt/DataManagement/mitkSetObserver.h index 6e33489896..3ff65a896a 100644 --- a/Modules/MitkExt/DataManagement/mitkSetObserver.h +++ b/Modules/MitkExt/DataManagement/mitkSetObserver.h @@ -1,30 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKSETOBSERVER_H #define MITKSETOBSERVER_H namespace mitk { /// /// abstract base class for all objects observing an mitk::Set /// template struct SetObserver { virtual void OnAdded( T object ) {} virtual void OnModified( T object ) {} /// /// Will be called before an object gets removed /// virtual void OnRemove( T object ) {} virtual void OnDelete( T object ) {} /// /// Makes this class abstract /// virtual ~SetObserver() = 0; }; template SetObserver::~SetObserver() {} } #endif // MITKSETOBSERVER_H diff --git a/Modules/MitkExt/DataManagement/vtkObjectObserver.h b/Modules/MitkExt/DataManagement/vtkObjectObserver.h index a672746bb8..01b0e4e4e8 100644 --- a/Modules/MitkExt/DataManagement/vtkObjectObserver.h +++ b/Modules/MitkExt/DataManagement/vtkObjectObserver.h @@ -1,13 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef VTKOBJECTOBSERVER_H #define VTKOBJECTOBSERVER_H class vtkObject; class vtkObjectObserver { public: virtual void OnModified( const vtkObject* object ) = 0; virtual void OnDeleted( const vtkObject* object ) = 0; }; #endif // VTKOBJECTOBSERVER_H diff --git a/Modules/MitkExt/DataManagement/vtkObjectSet.cpp b/Modules/MitkExt/DataManagement/vtkObjectSet.cpp index 75a9da5faa..cca1d2ee75 100644 --- a/Modules/MitkExt/DataManagement/vtkObjectSet.cpp +++ b/Modules/MitkExt/DataManagement/vtkObjectSet.cpp @@ -1,76 +1,91 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "vtkObjectSet.h" #include "vtkObjectObserver.h" #include #include #include vtkObjectSet::vtkObjectSet() { } vtkObjectSet::~vtkObjectSet() { } void vtkObjectSet::AddObserver( vtkObjectObserver* observer ) { m_vtkObjectObservers.insert(observer); } void vtkObjectSet::RemoveObserver( vtkObjectObserver* observer ) { m_vtkObjectObservers.erase(observer); } void vtkObjectSet::AddObject ( vtkObject * obj ) { // if add object, add observer for modified and delete event std::pair::iterator, bool> res = m_Objects.insert(obj); if(res.second) { vtkSmartPointer modifiedCallback = vtkSmartPointer::New(); modifiedCallback->SetCallback ( vtkObjectSet::OnObjectModified ); modifiedCallback->SetClientData(this); m_ObjectModifiedTags[obj] = obj->AddObserver ( vtkCommand::ModifiedEvent, modifiedCallback ); m_ObjectDeleteTags[obj] = obj->AddObserver ( vtkCommand::DeleteEvent, modifiedCallback ); } } void vtkObjectSet::RemoveObject ( vtkObject * obj ) { // if object removed, remove observer and tags for modified and delete event std::set::size_type deletedObjs = m_Objects.erase(obj); if(deletedObjs > 0) { obj->RemoveObserver(m_ObjectModifiedTags[obj]); obj->RemoveObserver(m_ObjectDeleteTags[obj]); m_ObjectModifiedTags.erase(obj); m_ObjectDeleteTags.erase(obj); } } void vtkObjectSet::OnObjectModified(vtkObject* caller, unsigned long eid , void* clientdata, void * /*calldata*/) { // if event == modified event, inform objectobservers // else: call RemoveObject() or remove objectobserver and inform objectobservers vtkObjectSet* instance = static_cast( clientdata ); for(std::set::iterator it = instance->m_vtkObjectObservers.begin(); it != instance->m_vtkObjectObservers.end(); ++it) eid == vtkCommand::ModifiedEvent ? (*it)->OnModified( caller ): (*it)->OnDeleted( caller ); if(eid != vtkCommand::ModifiedEvent) instance->RemoveObject( caller ); } diff --git a/Modules/MitkExt/DataManagement/vtkObjectSet.h b/Modules/MitkExt/DataManagement/vtkObjectSet.h index 923b4f6290..6487282f1d 100644 --- a/Modules/MitkExt/DataManagement/vtkObjectSet.h +++ b/Modules/MitkExt/DataManagement/vtkObjectSet.h @@ -1,51 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKvtkObjectSet_H #define MITKvtkObjectSet_H #include #include #include #include class vtkObjectObserver; /// /// a class holding /// a list of itk objects and/or vtk objects. /// the main idea of the class /// is that it listens to the modified /// and delete events of the objects /// and informs associated objectobservers. /// This eases the handling of the sometimes complicated /// event handling mechanisms. /// class MitkExt_EXPORT vtkObjectSet { public: vtkObjectSet(); virtual ~vtkObjectSet(); void AddObserver( vtkObjectObserver* observer ); void RemoveObserver( vtkObjectObserver* observer ); void AddObject ( vtkObject * obj ); void RemoveObject ( vtkObject * obj ); /// /// vtk event function /// static void OnObjectModified(vtkObject *, unsigned long eid , void* clientdata, void * /*calldata*/); protected: std::set m_vtkObjectObservers; std::set m_Objects; /// /// \brief Holds all tags of Modified Event Listeners. /// std::map m_ObjectModifiedTags; /// /// \brief Holds all tags of Modified Event Listeners. /// std::map m_ObjectDeleteTags; }; #endif // MITKvtkObjectSet_H diff --git a/Modules/MitkExt/Interactions/mitkErodeTool.cpp b/Modules/MitkExt/Interactions/mitkErodeTool.cpp index 0ce2ba9183..2fc738e0ea 100644 --- a/Modules/MitkExt/Interactions/mitkErodeTool.cpp +++ b/Modules/MitkExt/Interactions/mitkErodeTool.cpp @@ -1,72 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkErodeTool.h" #include "mitkImageCast.h" #include "mitkRenderingManager.h" namespace mitk{ MITK_TOOL_MACRO(MitkExt_EXPORT, ErodeTool, "Erode Tool"); } mitk::ErodeTool::ErodeTool() { } mitk::ErodeTool::~ErodeTool() { } const char* mitk::ErodeTool::GetName() const { return "Erode Tool"; } const char** mitk::ErodeTool::GetXPM() const { return mitkErodeTool_xpm; } mitk::Image::Pointer mitk::ErodeTool::ApplyFilter(mitk::Image::Pointer image) { SegmentationType::Pointer itkImage = SegmentationType::New(); mitk::CastToItkImage(image, itkImage); mitk::Image::Pointer new_image = mitk::Image::New(); switch(m_StructElement) { case(BALL): m_Ball.SetRadius( m_Radius); m_Ball.CreateStructuringElement(); m_BallErodeFilter = BallErodeFilterType::New(); m_BallErodeFilter->SetKernel(m_Ball); m_BallErodeFilter->SetInput(itkImage); m_BallErodeFilter->SetErodeValue(1); m_BallErodeFilter->BoundaryToForegroundOn(); m_BallErodeFilter->UpdateLargestPossibleRegion(); mitk::CastToMitkImage(m_BallErodeFilter->GetOutput(), new_image); break; case(CROSS): m_Cross.SetRadius(m_Radius); m_Cross.CreateStructuringElement(); m_CrossErodeFilter = CrossErodeFilterType::New(); m_CrossErodeFilter->SetKernel(m_Cross); m_CrossErodeFilter->SetInput(itkImage); m_CrossErodeFilter->SetErodeValue(1); m_CrossErodeFilter->BoundaryToForegroundOn(); m_CrossErodeFilter->UpdateLargestPossibleRegion(); mitk::CastToMitkImage(m_CrossErodeFilter->GetOutput(), new_image); break; default: break; } return new_image; } \ No newline at end of file diff --git a/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.cpp b/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.cpp index b70754f7ff..147cf36aae 100644 --- a/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.cpp +++ b/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.cpp @@ -1,652 +1,667 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkMitkGPUVolumeRayCastMapper.h" // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) #include "vtkVolumeRenderingFactory.h" #include "vtkImageData.h" #include "vtkPointData.h" #include "vtkCellData.h" #include "vtkDataArray.h" #include "vtkTimerLog.h" #include "vtkImageResample.h" #include "vtkVolume.h" #include "vtkVolumeProperty.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include #include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event #include "vtkCamera.h" #include "vtkRendererCollection.h" #include "vtkMultiThreader.h" #include "vtkGPUInfoList.h" #include "vtkGPUInfo.h" vtkCxxRevisionMacro(vtkMitkGPUVolumeRayCastMapper, "$Revision: 1.7 $"); vtkInstantiatorNewMacro(vtkMitkGPUVolumeRayCastMapper); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, MaskInput, vtkImageData); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, TransformedInput, vtkImageData); vtkMitkGPUVolumeRayCastMapper::vtkMitkGPUVolumeRayCastMapper() { this->AutoAdjustSampleDistances = 1; this->ImageSampleDistance = 1.0; this->MinimumImageSampleDistance = 1.0; this->MaximumImageSampleDistance = 10.0; this->SampleDistance = 1.0; this->SmallVolumeRender = 0; this->BigTimeToDraw = 0.0; this->SmallTimeToDraw = 0.0; this->FinalColorWindow = 1.0; this->FinalColorLevel = 0.5; this->GeneratingCanonicalView = 0; this->CanonicalViewImageData = NULL; this->MaskInput = NULL; this->MaskBlendFactor=1.0f; this->AMRMode=0; this->ClippedCroppingRegionPlanes[0]=VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[1]=VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[2]=VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[3]=VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[4]=VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[5]=VTK_DOUBLE_MIN; this->MaxMemoryInBytes=0; vtkGPUInfoList *l=vtkGPUInfoList::New(); l->Probe(); if(l->GetNumberOfGPUs()>0) { vtkGPUInfo *info=l->GetGPUInfo(0); this->MaxMemoryInBytes=info->GetDedicatedVideoMemory(); if(this->MaxMemoryInBytes==0) { this->MaxMemoryInBytes=info->GetDedicatedSystemMemory(); } // we ignore info->GetSharedSystemMemory(); as this is very slow. } l->Delete(); if(this->MaxMemoryInBytes==0) // use some default value: 128MB. { this->MaxMemoryInBytes=128*1024*1024; } this->MaxMemoryFraction = 0.75; this->ReportProgress=true; this->TransformedInput = NULL; this->LastInput = NULL; } // ---------------------------------------------------------------------------- vtkMitkGPUVolumeRayCastMapper::~vtkMitkGPUVolumeRayCastMapper() { this->SetMaskInput(NULL); this->SetTransformedInput(NULL); this->LastInput = NULL; } // ---------------------------------------------------------------------------- vtkMitkGPUVolumeRayCastMapper *vtkMitkGPUVolumeRayCastMapper::New() { // First try to create the object from the vtkObjectFactory vtkObject* ret = vtkVolumeRenderingFactory::CreateInstance("vtkMitkGPUVolumeRayCastMapper"); return static_cast(ret); } // ---------------------------------------------------------------------------- // The render method that is called from the volume. If this is a canonical // view render, a specialized version of this method will be called instead. // Otherwise we will // - Invoke a start event // - Start timing // - Check that everything is OK for rendering // - Render // - Stop the timer and record results // - Invoke an end event // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::Render( vtkRenderer *ren, vtkVolume *vol ) { // Catch renders that are happening due to a canonical view render and // handle them separately. if (this->GeneratingCanonicalView ) { this->CanonicalViewRender(ren, vol); return; } // Invoke a VolumeMapperRenderStartEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderStartEvent,0); // Start the timer to time the length of this render vtkTimerLog *timer = vtkTimerLog::New(); timer->StartTimer(); // Make sure everything about this render is OK. // This is where the input is updated. if ( this->ValidateRender(ren, vol ) ) { // Everything is OK - so go ahead and really do the render this->GPURender( ren, vol); } // Stop the timer timer->StopTimer(); double t = timer->GetElapsedTime(); // cout << "Render Timer " << t << " seconds, " << 1.0/t << " frames per second" << endl; this->TimeToDraw = t; timer->Delete(); if ( vol->GetAllocatedRenderTime() < 1.0 ) { this->SmallTimeToDraw = t; } else { this->BigTimeToDraw = t; } // Invoke a VolumeMapperRenderEndEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderEndEvent,0); } // ---------------------------------------------------------------------------- // Special version for rendering a canonical view - we don't do things like // invoke start or end events, and we don't capture the render time. // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CanonicalViewRender(vtkRenderer *ren, vtkVolume *vol ) { // Make sure everything about this render is OK if ( this->ValidateRender(ren, vol ) ) { // Everything is OK - so go ahead and really do the render this->GPURender( ren, vol); } } // ---------------------------------------------------------------------------- // This method us used by the render method to validate everything before // attempting to render. This method returns 0 if something is not right - // such as missing input, a null renderer or a null volume, no scalars, etc. // In some cases it will produce a vtkErrorMacro message, and in others // (for example, in the case of cropping planes that define a region with // a volume or 0 or less) it will fail silently. If everything is OK, it will // return with a value of 1. // ---------------------------------------------------------------------------- int vtkMitkGPUVolumeRayCastMapper::ValidateRender(vtkRenderer *ren, vtkVolume *vol) { // Check that we have everything we need to render. int goodSoFar = 1; // Check for a renderer - we MUST have one if ( !ren ) { goodSoFar = 0; vtkErrorMacro("Renderer cannot be null."); } // Check for the volume - we MUST have one if ( goodSoFar && !vol ) { goodSoFar = 0; vtkErrorMacro("Volume cannot be null."); } // Don't need to check if we have a volume property // since the volume will create one if we don't. Also // don't need to check for the scalar opacity function // or the RGB transfer function since the property will // create them if they do not yet exist. // However we must currently check that the number of // color channels is 3 // TODO: lift this restriction - should work with // gray functions as well. Right now turning off test // because otherwise 4 component rendering isn't working. // Will revisit. if ( goodSoFar && vol->GetProperty()->GetColorChannels() != 3 ) { // goodSoFar = 0; // vtkErrorMacro("Must have a color transfer function."); } // Check the cropping planes. If they are invalid, just silently // fail. This will happen when an interactive widget is dragged // such that it defines 0 or negative volume - this can happen // and should just not render the volume. // Check the cropping planes if( goodSoFar && this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] || this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] || this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5] )) { // No error message here - we want to be silent goodSoFar = 0; } // Check that we have input data vtkImageData *input=this->GetInput(); // If we have a timestamp change or data change then create a new clone. if(input != this->LastInput || input->GetMTime() > this->TransformedInput->GetMTime()) { this->LastInput = input; vtkImageData* clone; if(!this->TransformedInput) { clone = vtkImageData::New(); this->SetTransformedInput(clone); clone->Delete(); } else { clone = this->TransformedInput; } clone->ShallowCopy(input); // @TODO: This is the workaround to deal with GPUVolumeRayCastMapper // not able to handle extents starting from non zero values. // There is not a easy fix in the GPU volume ray cast mapper hence // this fix has been introduced. // Get the current extents. int extents[6], real_extents[6]; clone->GetExtent(extents); clone->GetExtent(real_extents); // Get the current origin and spacing. double origin[3], spacing[3]; clone->GetOrigin(origin); clone->GetSpacing(spacing); for (int cc=0; cc < 3; cc++) { // Transform the origin and the extents. origin[cc] = origin[cc] + extents[2*cc]*spacing[cc]; extents[2*cc+1] -= extents[2*cc]; extents[2*cc] -= extents[2*cc]; } clone->SetOrigin(origin); clone->SetExtent(extents); } if ( goodSoFar && !this->TransformedInput ) { vtkErrorMacro("Input is NULL but is required"); goodSoFar = 0; } // Update the date then make sure we have scalars. Note // that we must have point or cell scalars because field // scalars are not supported. vtkDataArray *scalars = NULL; if ( goodSoFar ) { // Here is where we update the input this->TransformedInput->UpdateInformation(); this->TransformedInput->SetUpdateExtentToWholeExtent(); this->TransformedInput->Update(); // Now make sure we can find scalars scalars=this->GetScalars(this->TransformedInput,this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); // We couldn't find scalars if ( !scalars ) { vtkErrorMacro("No scalars found on input."); goodSoFar = 0; } // Even if we found scalars, if they are field data scalars that isn't good else if ( this->CellFlag == 2 ) { vtkErrorMacro("Only point or cell scalar support - found field scalars instead."); goodSoFar = 0; } } // Make sure the scalar type is actually supported. This mappers supports // almost all standard scalar types. if ( goodSoFar ) { switch(scalars->GetDataType()) { case VTK_CHAR: vtkErrorMacro(<< "scalar of type VTK_CHAR is not supported " << "because this type is platform dependent. " << "Use VTK_SIGNED_CHAR or VTK_UNSIGNED_CHAR instead."); goodSoFar = 0; break; case VTK_BIT: vtkErrorMacro("scalar of type VTK_BIT is not supported by this mapper."); goodSoFar = 0; break; case VTK_ID_TYPE: vtkErrorMacro("scalar of type VTK_ID_TYPE is not supported by this mapper."); goodSoFar = 0; break; case VTK_STRING: vtkErrorMacro("scalar of type VTK_STRING is not supported by this mapper."); goodSoFar = 0; break; default: // Don't need to do anything here break; } } // Check on the blending type - we support composite and min / max intensity if ( goodSoFar ) { if(this->BlendMode!=vtkVolumeMapper::COMPOSITE_BLEND && this->BlendMode!=vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND && this->BlendMode!=vtkVolumeMapper::MINIMUM_INTENSITY_BLEND) { goodSoFar = 0; vtkErrorMacro(<< "Selected blend mode not supported. " << "Only Composite and MIP and MinIP modes " << "are supported by the current implementation."); } } // This mapper supports 1 component data, or 4 component if it is not independent // component (i.e. the four components define RGBA) int numberOfComponents = 0; if ( goodSoFar ) { numberOfComponents=scalars->GetNumberOfComponents(); if( !( numberOfComponents==1 || (numberOfComponents==4 && vol->GetProperty()->GetIndependentComponents()==0))) { goodSoFar = 0; vtkErrorMacro(<< "Only one component scalars, or four " << "component with non-independent components, " << "are supported by this mapper."); } } // If this is four component data, then it better be unsigned char (RGBA). if( goodSoFar && numberOfComponents == 4 && scalars->GetDataType() != VTK_UNSIGNED_CHAR) { goodSoFar = 0; vtkErrorMacro("Only unsigned char is supported for 4-component scalars!"); } // return our status return goodSoFar; } // ---------------------------------------------------------------------------- // Description: // Called by the AMR Volume Mapper. // Set the flag that tells if the scalars are on point data (0) or // cell data (1). void vtkMitkGPUVolumeRayCastMapper::SetCellFlag(int cellFlag) { this->CellFlag=cellFlag; } // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CreateCanonicalView( vtkRenderer *ren, vtkVolume *volume, vtkImageData *image, int vtkNotUsed(blend_mode), double viewDirection[3], double viewUp[3]) { this->GeneratingCanonicalView = 1; int oldSwap = ren->GetRenderWindow()->GetSwapBuffers(); ren->GetRenderWindow()->SwapBuffersOff(); int dim[3]; image->GetDimensions(dim); int *size = ren->GetRenderWindow()->GetSize(); vtkImageData *bigImage = vtkImageData::New(); bigImage->SetDimensions(size[0], size[1], 1); bigImage->SetScalarTypeToUnsignedChar(); bigImage->SetNumberOfScalarComponents(3); bigImage->AllocateScalars(); this->CanonicalViewImageData = bigImage; double scale[2]; scale[0] = dim[0] / static_cast(size[0]); scale[1] = dim[1] / static_cast(size[1]); // Save the visibility flags of the renderers and set all to false except // for the ren. vtkRendererCollection *renderers=ren->GetRenderWindow()->GetRenderers(); int numberOfRenderers=renderers->GetNumberOfItems(); bool *rendererVisibilities=new bool[numberOfRenderers]; renderers->InitTraversal(); int i=0; while(iGetNextItem(); rendererVisibilities[i]=r->GetDraw()==1; if(r!=ren) { r->SetDraw(false); } ++i; } // Save the visibility flags of the props and set all to false except // for the volume. vtkPropCollection *props=ren->GetViewProps(); int numberOfProps=props->GetNumberOfItems(); bool *propVisibilities=new bool[numberOfProps]; props->InitTraversal(); i=0; while(iGetNextProp(); propVisibilities[i]=p->GetVisibility()==1; if(p!=volume) { p->SetVisibility(false); } ++i; } vtkCamera *savedCamera=ren->GetActiveCamera(); savedCamera->Modified(); vtkCamera *canonicalViewCamera=vtkCamera::New(); // Code from vtkFixedPointVolumeRayCastMapper: double *center=volume->GetCenter(); double bounds[6]; volume->GetBounds(bounds); double d=sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); // For now use x distance - need to change this d=bounds[1]-bounds[0]; // Set up the camera in parallel canonicalViewCamera->SetFocalPoint(center); canonicalViewCamera->ParallelProjectionOn(); canonicalViewCamera->SetPosition(center[0] - d*viewDirection[0], center[1] - d*viewDirection[1], center[2] - d*viewDirection[2]); canonicalViewCamera->SetViewUp(viewUp); canonicalViewCamera->SetParallelScale(d/2); ren->SetActiveCamera(canonicalViewCamera); ren->GetRenderWindow()->Render(); ren->SetActiveCamera(savedCamera); canonicalViewCamera->Delete(); // Shrink to image to the desired size vtkImageResample *resample = vtkImageResample::New(); resample->SetInput( bigImage ); resample->SetAxisMagnificationFactor(0,scale[0]); resample->SetAxisMagnificationFactor(1,scale[1]); resample->SetAxisMagnificationFactor(2,1); resample->UpdateWholeExtent(); // Copy the pixels over image->DeepCopy(resample->GetOutput()); bigImage->Delete(); resample->Delete(); // Restore the visibility flags of the props props->InitTraversal(); i=0; while(iGetNextProp(); p->SetVisibility(propVisibilities[i]); ++i; } delete[] propVisibilities; // Restore the visibility flags of the renderers renderers->InitTraversal(); i=0; while(iGetNextItem(); r->SetDraw(rendererVisibilities[i]); ++i; } delete[] rendererVisibilities; ren->GetRenderWindow()->SetSwapBuffers(oldSwap); this->CanonicalViewImageData = NULL; this->GeneratingCanonicalView = 0; } // ---------------------------------------------------------------------------- // Print method for vtkMitkGPUVolumeRayCastMapper void vtkMitkGPUVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AutoAdjustSampleDistances: " << this->AutoAdjustSampleDistances << endl; os << indent << "MinimumImageSampleDistance: " << this->MinimumImageSampleDistance << endl; os << indent << "MaximumImageSampleDistance: " << this->MaximumImageSampleDistance << endl; os << indent << "ImageSampleDistance: " << this->ImageSampleDistance << endl; os << indent << "SampleDistance: " << this->SampleDistance << endl; os << indent << "FinalColorWindow: " << this->FinalColorWindow << endl; os << indent << "FinalColorLevel: " << this->FinalColorLevel << endl; os << indent << "MaskInput: " << this->MaskInput << endl; os << indent << "MaskBlendFactor: " << this->MaskBlendFactor << endl; os << indent << "MaxMemoryInBytes: " << this->MaxMemoryInBytes << endl; os << indent << "MaxMemoryFraction: " << this->MaxMemoryFraction << endl; os << indent << "ReportProgress: " << this->ReportProgress << endl; } // ---------------------------------------------------------------------------- // Description: // Compute the cropping planes clipped by the bounds of the volume. // The result is put into this->ClippedCroppingRegionPlanes. // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes // members instead of CroppingRegionPlanes. // \pre volume_exists: this->GetInput()!=0 // \pre valid_cropping: this->Cropping && // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) void vtkMitkGPUVolumeRayCastMapper::ClipCroppingRegionPlanes() { assert("pre: volume_exists" && this->GetInput()!=0); assert("pre: valid_cropping" && this->Cropping && this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]); // vtkVolumeMapper::Render() will have something like: // if(this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] || // this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] || // this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5])) // { // // silentely stop because the cropping is not valid. // return; // } double volBounds[6]; this->GetInput()->GetBounds(volBounds); int i=0; while(i<6) { // max of the mins if(this->CroppingRegionPlanes[i]ClippedCroppingRegionPlanes[i]=volBounds[i]; } else { this->ClippedCroppingRegionPlanes[i]=this->CroppingRegionPlanes[i]; } ++i; // min of the maxs if(this->CroppingRegionPlanes[i]>volBounds[i]) { this->ClippedCroppingRegionPlanes[i]=volBounds[i]; } else { this->ClippedCroppingRegionPlanes[i]=this->CroppingRegionPlanes[i]; } ++i; } } #endif \ No newline at end of file diff --git a/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.h b/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.h index c0d30cb23a..b5122037da 100644 --- a/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.h +++ b/Modules/MitkExt/Rendering/vtkMitkGPUVolumeRayCastMapper.h @@ -1,294 +1,309 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkMitkGPUVolumeRayCastMapper - Ray casting performed on the GPU. // .SECTION Description // vtkMitkGPUVolumeRayCastMapper is a volume mapper that performs ray casting on // the GPU using fragment programs. // #ifndef __vtkMitkGPUVolumeRayCastMapper_h #define __vtkMitkGPUVolumeRayCastMapper_h #include "vtkVolumeMapper.h" #include "mitkCommon.h" #include "MitkExtExports.h" // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) class vtkVolumeProperty; class vtkRenderWindow; //class vtkKWAMRVolumeMapper; // friend class. class MitkExt_EXPORT vtkMitkGPUVolumeRayCastMapper : public vtkVolumeMapper { public: static vtkMitkGPUVolumeRayCastMapper *New(); vtkTypeRevisionMacro(vtkMitkGPUVolumeRayCastMapper,vtkVolumeMapper); void PrintSelf( ostream& os, vtkIndent indent ); // Description: // If AutoAdjustSampleDistances is on, the the ImageSampleDistance // will be varied to achieve the allocated render time of this // prop (controlled by the desired update rate and any culling in // use). vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); vtkGetMacro( AutoAdjustSampleDistances, int ); vtkBooleanMacro( AutoAdjustSampleDistances, int ); // Description: // Set/Get the distance between samples used for rendering // when AutoAdjustSampleDistances is off, or when this mapper // has more than 1 second allocated to it for rendering. // Initial value is 1.0. vtkSetMacro( SampleDistance, float ); vtkGetMacro( SampleDistance, float ); // Description: // Sampling distance in the XY image dimensions. Default value of 1 meaning // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value // will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances // is on. vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); vtkGetMacro( ImageSampleDistance, float ); // Description: // This is the minimum image sample distance allow when the image // sample distance is being automatically adjusted. vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); vtkGetMacro( MinimumImageSampleDistance, float ); // Description: // This is the maximum image sample distance allow when the image // sample distance is being automatically adjusted. vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); vtkGetMacro( MaximumImageSampleDistance, float ); // Description: // Set/Get the window / level applied to the final color. // This allows brightness / contrast adjustments on the // final image. // window is the width of the window. // level is the center of the window. // Initial window value is 1.0 // Initial level value is 0.5 // window cannot be null but can be negative, this way // values will be reversed. // |window| can be larger than 1.0 // level can be any real value. vtkSetMacro( FinalColorWindow, float ); vtkGetMacro( FinalColorWindow, float ); vtkSetMacro( FinalColorLevel, float ); vtkGetMacro( FinalColorLevel, float ); // Description: // Maximum size of the 3D texture in GPU memory. // Will default to the size computed from the graphics // card. Can be adjusted by the user. vtkSetMacro( MaxMemoryInBytes, vtkIdType ); vtkGetMacro( MaxMemoryInBytes, vtkIdType ); // Description: // Maximum fraction of the MaxMemoryInBytes that should // be used to hold the texture. Valid values are 0.1 to // 1.0. vtkSetClampMacro( MaxMemoryFraction, float, 0.1f, 1.0f ); vtkGetMacro( MaxMemoryFraction, float ); // Description: // Tells if the mapper will report intermediate progress. // Initial value is true. As the progress works with a GL blocking // call (glFinish()), this can be useful for huge dataset but can // slow down rendering of small dataset. It should be set to true // for big dataset or complex shading and streaming but to false for // small datasets. vtkSetMacro(ReportProgress,bool); vtkGetMacro(ReportProgress,bool); // Description: // Based on hardware and properties, we may or may not be able to // render using 3D texture mapping. This indicates if 3D texture // mapping is supported by the hardware, and if the other extensions // necessary to support the specific properties are available. virtual int IsRenderSupported(vtkRenderWindow *vtkNotUsed(window), vtkVolumeProperty *vtkNotUsed(property)) { return 0; } void CreateCanonicalView( vtkRenderer *ren, vtkVolume *volume, vtkImageData *image, int blend_mode, double viewDirection[3], double viewUp[3] ); void SetMaskInput(vtkImageData *mask); vtkGetObjectMacro(MaskInput, vtkImageData); // Description: // Tells how much mask color transfer function is used compared to the // standard color transfer function when the mask is true. // 0.0 means only standard color transfer function. // 1.0 means only mask color tranfer function. // Initial value is 1.0. vtkSetClampMacro(MaskBlendFactor,float,0.0f,1.0f); vtkGetMacro(MaskBlendFactor,float); //BTX // Description: // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE // Initialize rendering for this volume. void Render( vtkRenderer *, vtkVolume * ); // Description: // Handled in the subclass - the actual render method // \pre input is up-to-date. virtual void GPURender( vtkRenderer *, vtkVolume *) {} // Description: // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE // Release any graphics resources that are being consumed by this mapper. // The parameter window could be used to determine which graphic // resources to release. void ReleaseGraphicsResources(vtkWindow *) {}; // Description: // Return how much the dataset has to be reduced in each dimension to // fit on the GPU. If the value is 1.0, there is no need to reduce the // dataset. // \pre the calling thread has a current OpenGL context. // \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) // The computation is based on hardware limits (3D texture indexable size) // and MaxMemoryInBytes. // \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 // \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 // \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 virtual void GetReductionRatio(double ratio[3])=0; //ETX protected: vtkMitkGPUVolumeRayCastMapper(); ~vtkMitkGPUVolumeRayCastMapper(); // Check to see that the render will be OK int ValidateRender( vtkRenderer *, vtkVolume * ); // Special version of render called during the creation // of a canonical view. void CanonicalViewRender( vtkRenderer *, vtkVolume * ); // Methods called by the AMR Volume Mapper. virtual void PreRender(vtkRenderer *ren, vtkVolume *vol, double datasetBounds[6], double scalarRange[2], int numberOfScalarComponents, unsigned int numberOfLevels)=0; // \pre input is up-to-date virtual void RenderBlock(vtkRenderer *ren, vtkVolume *vol, unsigned int level)=0; virtual void PostRender(vtkRenderer *ren, int numberOfScalarComponents)=0; // Description: // Called by the AMR Volume Mapper. // Set the flag that tells if the scalars are on point data (0) or // cell data (1). void SetCellFlag(int cellFlag); // The distance between sample points along the ray float SampleDistance; float ImageSampleDistance; float MinimumImageSampleDistance; float MaximumImageSampleDistance; int AutoAdjustSampleDistances; int SmallVolumeRender; double BigTimeToDraw; double SmallTimeToDraw; float FinalColorWindow; float FinalColorLevel; vtkIdType MaxMemoryInBytes; float MaxMemoryFraction; // 1 if we are generating the canonical image, 0 otherwise int GeneratingCanonicalView; vtkImageData *CanonicalViewImageData; // Description: // Set the mapper in AMR Mode or not. Initial value is false. // Called only by the vtkKWAMRVolumeMapper vtkSetClampMacro(AMRMode,int,0,1); vtkGetMacro(AMRMode,int); vtkBooleanMacro(AMRMode,int); int AMRMode; int CellFlag; // point data or cell data (or field data, not handled) ? // Description: // Compute the cropping planes clipped by the bounds of the volume. // The result is put into this->ClippedCroppingRegionPlanes. // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes // members instead of CroppingRegionPlanes. // \pre volume_exists: this->GetInput()!=0 // \pre valid_cropping: this->Cropping && // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) virtual void ClipCroppingRegionPlanes(); double ClippedCroppingRegionPlanes[6]; bool ReportProgress; vtkImageData *MaskInput; float MaskBlendFactor; vtkGetObjectMacro(TransformedInput, vtkImageData); void SetTransformedInput(vtkImageData*); vtkImageData* TransformedInput; // Description: // This is needed only to check if the input data has been changed since the last // Render() call. vtkImageData* LastInput; private: vtkMitkGPUVolumeRayCastMapper(const vtkMitkGPUVolumeRayCastMapper&); // Not implemented. void operator=(const vtkMitkGPUVolumeRayCastMapper&); // Not implemented. }; #endif #endif diff --git a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.cpp b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.cpp index 9faddb5017..37c17d4873 100644 --- a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.cpp +++ b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.cpp @@ -1,7342 +1,7357 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkOpenGLGPUVolumeRayCastMapper.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkMitkOpenGLGPUVolumeRayCastMapper.h" // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) #include "vtkObjectFactory.h" #include "vtkVolume.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkCamera.h" #include "vtkMatrix4x4.h" #include "vtkImageData.h" #include "vtkTimerLog.h" #include "vtkVolumeProperty.h" #include "vtkColorTransferFunction.h" #include "vtkPiecewiseFunction.h" #include "vtkOpenGLExtensionManager.h" #include "vtkgl.h" #ifndef VTK_IMPLEMENT_MESA_CXX # include "vtkOpenGL.h" #endif #include #include #include #include #include #include "vtkClipDataSet.h" #include "vtkCellArray.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkGeometryFilter.h" #include "vtkMath.h" #include "vtkPlane.h" #include "vtkPlaneCollection.h" #include "vtkPlanes.h" #include "vtkPolyData.h" #include "vtkPointData.h" #include "vtkCellData.h" #include "vtkPoints.h" #include "vtkUnsignedCharArray.h" #include "vtkUnsignedShortArray.h" #include "vtkUnsignedIntArray.h" #include "vtkUnstructuredGrid.h" #include "vtkVoxel.h" #include "vtkClipConvexPolyData.h" #include "vtkClipPolyData.h" #include "vtkDensifyPolyData.h" #include "vtkImageResample.h" #include #include // qsort() #include "vtkDataSetTriangleFilter.h" #include "vtkAbstractArray.h" // required if compiled against VTK 5.0 #include "vtkTessellatedBoxSource.h" #include "vtkCleanPolyData.h" #include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event #include "vtkPerlinNoise.h" #include #include "vtkStdString.h" //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class vtkUnsupportedRequiredExtensionsStringStream { public: vtkstd::ostringstream Stream; vtkUnsupportedRequiredExtensionsStringStream() { } private: // undefined copy constructor. vtkUnsupportedRequiredExtensionsStringStream(const vtkUnsupportedRequiredExtensionsStringStream &other); // undefined assignment operator. vtkUnsupportedRequiredExtensionsStringStream &operator=(const vtkUnsupportedRequiredExtensionsStringStream &other); }; class vtkMapDataArrayTextureId { public: vtkstd::map Map; vtkMapDataArrayTextureId() { } private: // undefined copy constructor. vtkMapDataArrayTextureId(const vtkMapDataArrayTextureId &other); // undefined assignment operator. vtkMapDataArrayTextureId &operator=(const vtkMapDataArrayTextureId &other); }; class vtkMapMaskTextureId { public: vtkstd::map Map; vtkMapMaskTextureId() { } private: // undefined copy constructor. vtkMapMaskTextureId(const vtkMapMaskTextureId &other); // undefined assignment operator. vtkMapMaskTextureId &operator=(const vtkMapMaskTextureId &other); }; //----------------------------------------------------------------------------- extern const char *vtkMitkGPUVolumeRayCastMapper_CompositeFS; extern const char *vtkMitkGPUVolumeRayCastMapper_CompositeCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_CompositeNoCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_HeaderFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentNoCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MIPNoCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_ParallelProjectionFS; extern const char *vtkMitkGPUVolumeRayCastMapper_PerspectiveProjectionFS; extern const char *vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentNoCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_MinIPNoCroppingFS; extern const char *vtkMitkGPUVolumeRayCastMapper_CompositeMaskFS; extern const char *vtkMitkGPUVolumeRayCastMapper_NoShadeFS; extern const char *vtkMitkGPUVolumeRayCastMapper_ShadeFS; extern const char *vtkMitkGPUVolumeRayCastMapper_OneComponentFS; extern const char *vtkMitkGPUVolumeRayCastMapper_FourComponentsFS; enum { vtkMitkOpenGLGPUVolumeRayCastMapperProjectionNotInitialized=-1, // not init vtkMitkOpenGLGPUVolumeRayCastMapperProjectionPerspective=0, // false vtkMitkOpenGLGPUVolumeRayCastMapperProjectionParallel=1 // true }; enum { vtkMitkOpenGLGPUVolumeRayCastMapperMethodNotInitialized, vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP, vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIPFourDependent, vtkMitkOpenGLGPUVolumeRayCastMapperMethodComposite, vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIP, vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIPFourDependent, vtkMitkOpenGLGPUVolumeRayCastMapperMethodCompositeMask }; // component implementation enum { vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotInitialized=-1, // not init vtkMitkOpenGLGPUVolumeRayCastMapperComponentOne=0, // false vtkMitkOpenGLGPUVolumeRayCastMapperComponentFour=1, // true vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotUsed=2 // when not composite }; // Shade implementation enum { vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotInitialized=-1, // not init vtkMitkOpenGLGPUVolumeRayCastMapperShadeNo=0, // false vtkMitkOpenGLGPUVolumeRayCastMapperShadeYes=1, // true vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotUsed=2 // when not composite }; // Cropping implementation enum { vtkMitkOpenGLGPUVolumeRayCastMapperCroppingNotInitialized, vtkMitkOpenGLGPUVolumeRayCastMapperCompositeCropping, vtkMitkOpenGLGPUVolumeRayCastMapperCompositeNoCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMIPCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMIPNoCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMIPFourDependentCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMIPFourDependentNoCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMinIPCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMinIPNoCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMinIPFourDependentCropping, vtkMitkOpenGLGPUVolumeRayCastMapperMinIPFourDependentNoCropping }; enum { vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectDepthMap=0, // 2d texture vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront // 2d texture }; const int vtkMitkOpenGLGPUVolumeRayCastMapperNumberOfTextureObjects=vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+2; const int vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize=1024; //power of two #ifndef VTK_IMPLEMENT_MESA_CXX vtkCxxRevisionMacro(vtkMitkOpenGLGPUVolumeRayCastMapper, "$Revision: 1.9 $"); vtkStandardNewMacro(vtkMitkOpenGLGPUVolumeRayCastMapper); #endif //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class vtkOpacityTable { public: vtkOpacityTable() { this->TextureId=0; this->LastBlendMode=vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND; this->LastSampleDistance=1.0; this->Table=0; this->Loaded=false; this->LastLinearInterpolation=false; } ~vtkOpacityTable() { if(this->TextureId!=0) { glDeleteTextures(1,&this->TextureId); this->TextureId=0; } if(this->Table!=0) { delete[] this->Table; this->Table=0; } } bool IsLoaded() { return this->Loaded; } void Bind() { assert("pre: uptodate" && this->Loaded); glBindTexture(GL_TEXTURE_1D,this->TextureId); } // \pre the active texture is set to TEXTURE2 void Update(vtkPiecewiseFunction *scalarOpacity, int blendMode, double sampleDistance, double range[2], double unitDistance, bool linearInterpolation) { assert("pre: scalarOpacity_exists" && scalarOpacity!=0); bool needUpdate=false; if(this->TextureId==0) { glGenTextures(1,&this->TextureId); needUpdate=true; } glBindTexture(GL_TEXTURE_1D,this->TextureId); if(needUpdate) { glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); } if(scalarOpacity->GetMTime() > this->BuildTime || (this->LastBlendMode!=blendMode) || (blendMode==vtkVolumeMapper::COMPOSITE_BLEND && this->LastSampleDistance!=sampleDistance) || needUpdate || !this->Loaded) { this->Loaded=false; if(this->Table==0) { this->Table= new float[vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize]; } scalarOpacity->GetTable(range[0],range[1], vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize, this->Table); this->LastBlendMode=blendMode; // Correct the opacity array for the spacing between the planes if we // are using a composite blending operation if(blendMode==vtkVolumeMapper::COMPOSITE_BLEND) { float *ptr=this->Table; double factor=sampleDistance/unitDistance; int i=0; while(i0.0001f) { *ptr=static_cast(1.0-pow(1.0-static_cast(*ptr), factor)); } ++ptr; ++i; } this->LastSampleDistance=sampleDistance; } glTexImage1D(GL_TEXTURE_1D,0,GL_ALPHA16, vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize,0, GL_ALPHA,GL_FLOAT,this->Table); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("1d opacity texture is too large"); this->Loaded=true; this->BuildTime.Modified(); } needUpdate=needUpdate || this->LastLinearInterpolation!=linearInterpolation; if(needUpdate) { this->LastLinearInterpolation=linearInterpolation; GLint value; if(linearInterpolation) { value=GL_LINEAR; } else { value=GL_NEAREST; } glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,value); glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,value); } } protected: GLuint TextureId; int LastBlendMode; double LastSampleDistance; vtkTimeStamp BuildTime; float *Table; bool Loaded; bool LastLinearInterpolation; }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class vtkOpacityTables { public: vtkstd::vector Vector; vtkOpacityTables(size_t numberOfLevels) : Vector(numberOfLevels) { } private: // undefined copy constructor. vtkOpacityTables(const vtkOpacityTables &other); // undefined assignment operator. vtkOpacityTables &operator=(const vtkOpacityTables &other); }; //----------------------------------------------------------------------------- class vtkRGBTable { public: vtkRGBTable() { this->TextureId=0; this->Table=0; this->Loaded=false; this->LastLinearInterpolation=false; } ~vtkRGBTable() { if(this->TextureId!=0) { glDeleteTextures(1,&this->TextureId); this->TextureId=0; } if(this->Table!=0) { delete[] this->Table; this->Table=0; } } bool IsLoaded() { return this->Loaded; } void Bind() { assert("pre: uptodate" && this->Loaded); glBindTexture(GL_TEXTURE_1D,this->TextureId); } // \pre the active texture is set properly. (default color, // mask1, mask2,..) void Update(vtkColorTransferFunction *scalarRGB, double range[2], bool linearInterpolation) { assert("pre: scalarRGB_exists" && scalarRGB!=0); bool needUpdate=false; if(this->TextureId==0) { glGenTextures(1,&this->TextureId); needUpdate=true; } glBindTexture(GL_TEXTURE_1D,this->TextureId); if(needUpdate) { glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); } if(scalarRGB->GetMTime() > this->BuildTime || needUpdate || !this->Loaded) { this->Loaded=false; if(this->Table==0) { this->Table= new float[vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize*3]; } scalarRGB->GetTable(range[0],range[1], vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize, this->Table); glTexImage1D(GL_TEXTURE_1D,0,GL_RGB16, vtkMitkOpenGLGPUVolumeRayCastMapperOpacityTableSize,0, GL_RGB,GL_FLOAT,this->Table); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("1d RGB texture is too large"); this->Loaded=true; this->BuildTime.Modified(); } needUpdate=needUpdate || this->LastLinearInterpolation!=linearInterpolation; if(needUpdate) { this->LastLinearInterpolation=linearInterpolation; GLint value; if(linearInterpolation) { value=GL_LINEAR; } else { value=GL_NEAREST; } glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,value); glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,value); } } protected: GLuint TextureId; vtkTimeStamp BuildTime; float *Table; bool Loaded; bool LastLinearInterpolation; }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class vtkKWScalarField { public: vtkKWScalarField() { this->TextureId=0; this->Loaded=false; this->Supports_GL_ARB_texture_float=false; this->LoadedTableRange[0]=0.0; this->LoadedTableRange[1]=1.0; this->LoadedExtent[0]=VTK_INT_MAX; this->LoadedExtent[1]=VTK_INT_MIN; this->LoadedExtent[2]=VTK_INT_MAX; this->LoadedExtent[3]=VTK_INT_MIN; this->LoadedExtent[4]=VTK_INT_MAX; this->LoadedExtent[5]=VTK_INT_MIN; } ~vtkKWScalarField() { if(this->TextureId!=0) { glDeleteTextures(1,&this->TextureId); this->TextureId=0; } } vtkTimeStamp GetBuildTime() { return this->BuildTime; } void Bind() { assert("pre: uptodate" && this->Loaded); glBindTexture(vtkgl::TEXTURE_3D,this->TextureId); } void Update(vtkImageData *input, int cellFlag, int textureExtent[6], int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, bool linearInterpolation, double tableRange[2], int maxMemoryInBytes) { bool needUpdate=false; bool modified=false; if(this->TextureId==0) { glGenTextures(1,&this->TextureId); needUpdate=true; } glBindTexture(vtkgl::TEXTURE_3D,this->TextureId); int obsolete=needUpdate || !this->Loaded || input->GetMTime()>this->BuildTime; if(!obsolete) { obsolete=cellFlag!=this->LoadedCellFlag; int i=0; while(!obsolete && i<6) { obsolete=obsolete || this->LoadedExtent[i]>textureExtent[i]; ++i; obsolete=obsolete || this->LoadedExtent[i]LoadedTableRange[0]!=tableRange[0] || this->LoadedTableRange[1]!=tableRange[1]; } if(obsolete) { this->Loaded=false; int dim[3]; input->GetDimensions(dim); GLint internalFormat=0; GLenum format=0; GLenum type=0; // shift then scale: y:=(x+shift)*scale double shift=0.0; double scale=1.0; int needTypeConversion=0; vtkDataArray *sliceArray=0; vtkDataArray *scalars= vtkAbstractMapper::GetScalars(input,scalarMode,arrayAccessMode, arrayId,arrayName, this->LoadedCellFlag); // DONT USE GetScalarType() or GetNumberOfScalarComponents() on // ImageData as it deals only with point data... int scalarType=scalars->GetDataType(); if(scalars->GetNumberOfComponents()==4) { // this is RGBA, unsigned char only internalFormat=GL_RGBA16; format=GL_RGBA; type=GL_UNSIGNED_BYTE; } else { // input->GetNumberOfScalarComponents()==1 switch(scalarType) { case VTK_FLOAT: if(this->Supports_GL_ARB_texture_float) { internalFormat=vtkgl::INTENSITY16F_ARB; } else { internalFormat=GL_INTENSITY16; } format=GL_RED; type=GL_FLOAT; shift=-tableRange[0]; scale=1/(tableRange[1]-tableRange[0]); break; case VTK_UNSIGNED_CHAR: internalFormat=GL_INTENSITY8; format=GL_RED; type=GL_UNSIGNED_BYTE; shift=-tableRange[0]/VTK_UNSIGNED_CHAR_MAX; scale= VTK_UNSIGNED_CHAR_MAX/(tableRange[1]-tableRange[0]); break; case VTK_SIGNED_CHAR: internalFormat=GL_INTENSITY8; format=GL_RED; type=GL_BYTE; shift=-(2*tableRange[0]+1)/VTK_UNSIGNED_CHAR_MAX; scale=VTK_SIGNED_CHAR_MAX/(tableRange[1]-tableRange[0]); break; case VTK_CHAR: // not supported assert("check: impossible case" && 0); break; case VTK_BIT: // not supported assert("check: impossible case" && 0); break; case VTK_ID_TYPE: // not supported assert("check: impossible case" && 0); break; case VTK_INT: internalFormat=GL_INTENSITY16; format=GL_RED; type=GL_INT; shift=-(2*tableRange[0]+1)/VTK_UNSIGNED_INT_MAX; scale=VTK_INT_MAX/(tableRange[1]-tableRange[0]); break; case VTK_DOUBLE: case VTK___INT64: case VTK_LONG: case VTK_LONG_LONG: case VTK_UNSIGNED___INT64: case VTK_UNSIGNED_LONG: case VTK_UNSIGNED_LONG_LONG: needTypeConversion=1; // to float if(this->Supports_GL_ARB_texture_float) { internalFormat=vtkgl::INTENSITY16F_ARB; } else { internalFormat=GL_INTENSITY16; } format=GL_RED; type=GL_FLOAT; shift=-tableRange[0]; scale=1/(tableRange[1]-tableRange[0]); sliceArray=vtkFloatArray::New(); break; case VTK_SHORT: internalFormat=GL_INTENSITY16; format=GL_RED; type=GL_SHORT; shift=-(2*tableRange[0]+1)/VTK_UNSIGNED_SHORT_MAX; scale=VTK_SHORT_MAX/(tableRange[1]-tableRange[0]); break; case VTK_STRING: // not supported assert("check: impossible case" && 0); break; case VTK_UNSIGNED_SHORT: internalFormat=GL_INTENSITY16; format=GL_RED; type=GL_UNSIGNED_SHORT; shift=-tableRange[0]/VTK_UNSIGNED_SHORT_MAX; scale= VTK_UNSIGNED_SHORT_MAX/(tableRange[1]-tableRange[0]); break; case VTK_UNSIGNED_INT: internalFormat=GL_INTENSITY16; format=GL_RED; type=GL_UNSIGNED_INT; shift=-tableRange[0]/VTK_UNSIGNED_INT_MAX; scale=VTK_UNSIGNED_INT_MAX/(tableRange[1]-tableRange[0]); break; default: assert("check: impossible case" && 0); break; } } // Enough memory? int textureSize[3]; int i=0; while(i<3) { textureSize[i]=textureExtent[2*i+1]-textureExtent[2*i]+1; ++i; } GLint width; glGetIntegerv(vtkgl::MAX_3D_TEXTURE_SIZE,&width); this->Loaded=textureSize[0]<=width && textureSize[1]<=width && textureSize[2]<=width; if(this->Loaded) { // so far, so good. the texture size is theorically small enough // for OpenGL vtkgl::TexImage3D(vtkgl::PROXY_TEXTURE_3D,0,internalFormat, textureSize[0],textureSize[1],textureSize[2],0, format,type,0); glGetTexLevelParameteriv(vtkgl::PROXY_TEXTURE_3D,0,GL_TEXTURE_WIDTH, &width); this->Loaded=width!=0; if(this->Loaded) { // so far, so good but some cards always succeed with a proxy texture // let's try to actually allocate.. vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,internalFormat,textureSize[0], textureSize[1],textureSize[2],0,format,type,0); GLenum errorCode=glGetError(); this->Loaded=errorCode!=GL_OUT_OF_MEMORY; if(this->Loaded) { // so far, so good, actual allocation succeeded. if(errorCode!=GL_NO_ERROR) { cout<<"after try to load the texture"; cout<<" ERROR (x"<(errorCode)); cout<Loaded=textureSize[0]*textureSize[1]* textureSize[2]*vtkAbstractArray::GetDataTypeSize(scalarType)* scalars->GetNumberOfComponents()<=maxMemoryInBytes; if(this->Loaded) { // OK, we consider the allocation above succeeded... // If it actually didn't the only to fix it for the user // is to decrease the value of this->MaxMemoryInBytes. // enough memory! We can load the scalars! double bias=shift*scale; // we don't clamp to edge because for the computation of the // gradient on the border we need some external value. glTexParameterf(vtkgl::TEXTURE_3D,vtkgl::TEXTURE_WRAP_R,vtkgl::CLAMP_TO_EDGE); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_WRAP_S,vtkgl::CLAMP_TO_EDGE); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_WRAP_T,vtkgl::CLAMP_TO_EDGE); GLfloat borderColor[4]={0.0,0.0,0.0,0.0}; glTexParameterfv(vtkgl::TEXTURE_3D,GL_TEXTURE_BORDER_COLOR, borderColor); if(needTypeConversion) { // Convert and send to the GPU, z-slice by z-slice. // Allocate memory on the GPU (NULL data pointer with the right // dimensions) // Here we are assuming that GL_ARB_texture_non_power_of_two is // available glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // memory allocation is already done. // Send the slices: // allocate CPU memory for a slice. sliceArray->SetNumberOfComponents(1); // FB TODO CHECK THAT sliceArray->SetNumberOfTuples(textureSize[0]*textureSize[1]); void *slicePtr=sliceArray->GetVoidPointer(0); int k=0; int kInc=(dim[0]-cellFlag)*(dim[1]-cellFlag); int kOffset=(textureExtent[4]*(dim[1]-cellFlag) +textureExtent[2])*(dim[0]-cellFlag) +textureExtent[0]; while(kSetTuple1(jDestOffset+i, (scalars->GetTuple1(kOffset+jOffset +i) +shift)*scale); ++i; } ++j; jOffset+=dim[0]-cellFlag; jDestOffset+=textureSize[0]; } // Here we are assuming that GL_ARB_texture_non_power_of_two is // available vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D, 0, 0,0,k, textureSize[0],textureSize[1], 1, // depth is 1, not 0! format,type, slicePtr); ++k; kOffset+=kInc; } sliceArray->Delete(); } else { // One chunk of data to the GPU. // It works for the whole volume or for a subvolume. // Here we are assuming that GL_ARB_texture_non_power_of_two is // available // make sure any previous OpenGL call is executed and will not // be disturbed by our PixelTransfer value glFinish(); glPixelTransferf(GL_RED_SCALE,static_cast(scale)); glPixelTransferf(GL_RED_BIAS,static_cast(bias)); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); if(!(textureExtent[1]-textureExtent[0]+cellFlag==dim[0])) { glPixelStorei(GL_UNPACK_ROW_LENGTH,dim[0]-cellFlag); } if(!(textureExtent[3]-textureExtent[2]+cellFlag==dim[1])) { glPixelStorei(vtkgl::UNPACK_IMAGE_HEIGHT_EXT, dim[1]-cellFlag); } void *dataPtr=scalars->GetVoidPointer( ((textureExtent[4]*(dim[1]-cellFlag)+textureExtent[2]) *(dim[0]-cellFlag)+textureExtent[0]) *scalars->GetNumberOfComponents()); if(1) // !this->SupportsPixelBufferObjects) { vtkgl::TexImage3D(vtkgl::TEXTURE_3D, 0, internalFormat, textureSize[0],textureSize[1],textureSize[2], 0,format,type,dataPtr); } else { GLuint pbo=0; vtkgl::GenBuffers(1,&pbo); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("genbuffer"); vtkgl::BindBuffer(vtkgl::PIXEL_UNPACK_BUFFER,pbo); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("binbuffer"); vtkgl::GLsizeiptr texSize= textureSize[0]*textureSize[1]*textureSize[2]* vtkAbstractArray::GetDataTypeSize(scalarType)* scalars->GetNumberOfComponents(); vtkgl::BufferData(vtkgl::PIXEL_UNPACK_BUFFER,texSize,dataPtr, vtkgl::STREAM_DRAW); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("bufferdata"); vtkgl::TexImage3D(vtkgl::TEXTURE_3D, 0, internalFormat, textureSize[0],textureSize[1],textureSize[2], 0,format,type,0); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("teximage3d"); vtkgl::BindBuffer(vtkgl::PIXEL_UNPACK_BUFFER,0); vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("bindbuffer to 0"); vtkgl::DeleteBuffers(1,&pbo); } vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError("3d texture is too large2"); // make sure TexImage3D is executed with our PixelTransfer mode glFinish(); // Restore the default values. glPixelStorei(GL_UNPACK_ROW_LENGTH,0); glPixelStorei(vtkgl::UNPACK_IMAGE_HEIGHT_EXT,0); glPixelTransferf(GL_RED_SCALE,1.0); glPixelTransferf(GL_RED_BIAS,0.0); } this->LoadedCellFlag=cellFlag; i=0; while(i<6) { this->LoadedExtent[i]=textureExtent[i]; ++i; } double spacing[3]; double origin[3]; input->GetSpacing(spacing); input->GetOrigin(origin); int swapBounds[3]; swapBounds[0]=(spacing[0]<0); swapBounds[1]=(spacing[1]<0); swapBounds[2]=(spacing[2]<0); if(!this->LoadedCellFlag) // loaded extents represent points { // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2]; // in general, x=o+i*spacing. // if spacing is positive min extent match the min of the // bounding box // and the max extent match the max of the bounding box // if spacing is negative min extent match the max of the // bounding box // and the max extent match the min of the bounding box // if spacing is negative, we may have to rethink the equation // between real point and texture coordinate... this->LoadedBounds[0]=origin[0]+ static_cast(this->LoadedExtent[0+swapBounds[0]])*spacing[0]; this->LoadedBounds[2]=origin[1]+ static_cast(this->LoadedExtent[2+swapBounds[1]])*spacing[1]; this->LoadedBounds[4]=origin[2]+ static_cast(this->LoadedExtent[4+swapBounds[2]])*spacing[2]; this->LoadedBounds[1]=origin[0]+ static_cast(this->LoadedExtent[1-swapBounds[0]])*spacing[0]; this->LoadedBounds[3]=origin[1]+ static_cast(this->LoadedExtent[3-swapBounds[1]])*spacing[1]; this->LoadedBounds[5]=origin[2]+ static_cast(this->LoadedExtent[5-swapBounds[2]])*spacing[2]; } else // loaded extents represent cells { int wholeTextureExtent[6]; input->GetExtent(wholeTextureExtent); i=1; while(i<6) { wholeTextureExtent[i]--; i+=2; } i=0; while(i<3) { if(this->LoadedExtent[2*i]==wholeTextureExtent[2*i]) { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]; } else { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i])+0.5)*spacing[i]; } if(this->LoadedExtent[2*i+1]==wholeTextureExtent[2*i+1]) { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+1.0)*spacing[i]; } else { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+0.5)*spacing[i]; } ++i; } } this->LoadedTableRange[0]=tableRange[0]; this->LoadedTableRange[1]=tableRange[1]; modified=true; } // if enough memory else { } } //load fail with out of memory else { } } // proxy ok else { // proxy failed } } else { // out of therical limitationa } } // if obsolete if(this->Loaded && (needUpdate || modified || linearInterpolation!=this->LinearInterpolation)) { this->LinearInterpolation=linearInterpolation; if(this->LinearInterpolation) { glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MAG_FILTER, GL_NEAREST ); } modified=true; } if(modified) { this->BuildTime.Modified(); } } double *GetLoadedBounds() { assert("pre: loaded" && this->Loaded); return this->LoadedBounds; } vtkIdType *GetLoadedExtent() { assert("pre: loaded" && this->Loaded); return this->LoadedExtent; } int GetLoadedCellFlag() { assert("pre: loaded" && this->Loaded); return this->LoadedCellFlag; } bool IsLoaded() { return this->Loaded; } bool GetSupports_GL_ARB_texture_float() { return this->Supports_GL_ARB_texture_float; } void SetSupports_GL_ARB_texture_float(bool value) { this->Supports_GL_ARB_texture_float=value; } protected: GLuint TextureId; vtkTimeStamp BuildTime; double LoadedBounds[6]; vtkIdType LoadedExtent[6]; int LoadedCellFlag; bool Loaded; bool LinearInterpolation; bool Supports_GL_ARB_texture_float; double LoadedTableRange[2]; }; //----------------------------------------------------------------------------- class vtkKWMask { public: vtkKWMask() { this->TextureId=0; this->Loaded=false; this->LoadedExtent[0]=VTK_INT_MAX; this->LoadedExtent[1]=VTK_INT_MIN; this->LoadedExtent[2]=VTK_INT_MAX; this->LoadedExtent[3]=VTK_INT_MIN; this->LoadedExtent[4]=VTK_INT_MAX; this->LoadedExtent[5]=VTK_INT_MIN; } ~vtkKWMask() { if(this->TextureId!=0) { glDeleteTextures(1,&this->TextureId); this->TextureId=0; } } vtkTimeStamp GetBuildTime() { return this->BuildTime; } // \pre vtkgl::ActiveTexture(vtkgl::TEXTURE7) has to be called first. void Bind() { assert("pre: uptodate" && this->Loaded); glBindTexture(vtkgl::TEXTURE_3D,this->TextureId); } // \pre vtkgl::ActiveTexture(vtkgl::TEXTURE7) has to be called first. void Update(vtkImageData *input, int cellFlag, int textureExtent[6], int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, int maxMemoryInBytes) { bool needUpdate=false; bool modified=false; if(this->TextureId==0) { glGenTextures(1,&this->TextureId); needUpdate=true; } glBindTexture(vtkgl::TEXTURE_3D,this->TextureId); int obsolete=needUpdate || !this->Loaded || input->GetMTime()>this->BuildTime; if(!obsolete) { obsolete=cellFlag!=this->LoadedCellFlag; int i=0; while(!obsolete && i<6) { obsolete=obsolete || this->LoadedExtent[i]>textureExtent[i]; ++i; obsolete=obsolete || this->LoadedExtent[i]Loaded=false; int dim[3]; input->GetDimensions(dim); vtkDataArray *scalars= vtkAbstractMapper::GetScalars(input,scalarMode,arrayAccessMode, arrayId,arrayName, this->LoadedCellFlag); // DONT USE GetScalarType() or GetNumberOfScalarComponents() on // ImageData as it deals only with point data... int scalarType=scalars->GetDataType(); if(scalarType!=VTK_UNSIGNED_CHAR) { cout <<"mask should be VTK_UNSIGNED_CHAR." << endl; } if(scalars->GetNumberOfComponents()!=1) { cout <<"mask should be a one-component scalar field." << endl; } GLint internalFormat=GL_ALPHA8; GLenum format=GL_ALPHA; GLenum type=GL_UNSIGNED_BYTE; // Enough memory? int textureSize[3]; int i=0; while(i<3) { textureSize[i]=textureExtent[2*i+1]-textureExtent[2*i]+1; ++i; } GLint width; glGetIntegerv(vtkgl::MAX_3D_TEXTURE_SIZE,&width); this->Loaded=textureSize[0]<=width && textureSize[1]<=width && textureSize[2]<=width; if(this->Loaded) { // so far, so good. the texture size is theorically small enough // for OpenGL vtkgl::TexImage3D(vtkgl::PROXY_TEXTURE_3D,0,internalFormat, textureSize[0],textureSize[1],textureSize[2],0, format,type,0); glGetTexLevelParameteriv(vtkgl::PROXY_TEXTURE_3D,0,GL_TEXTURE_WIDTH, &width); this->Loaded=width!=0; if(this->Loaded) { // so far, so good but some cards always succeed with a proxy texture // let's try to actually allocate.. vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,internalFormat,textureSize[0], textureSize[1],textureSize[2],0,format,type,0); GLenum errorCode=glGetError(); this->Loaded=errorCode!=GL_OUT_OF_MEMORY; if(this->Loaded) { // so far, so good, actual allocation succeeded. if(errorCode!=GL_NO_ERROR) { cout<<"after try to load the texture"; cout<<" ERROR (x"<(errorCode)); cout<Loaded=textureSize[0]*textureSize[1]* textureSize[2]*vtkAbstractArray::GetDataTypeSize(scalarType)* scalars->GetNumberOfComponents()<=maxMemoryInBytes; if(this->Loaded) { // OK, we consider the allocation above succeeded... // If it actually didn't the only to fix it for the user // is to decrease the value of this->MaxMemoryInBytes. // enough memory! We can load the scalars! // we don't clamp to edge because for the computation of the // gradient on the border we need some external value. glTexParameterf(vtkgl::TEXTURE_3D,vtkgl::TEXTURE_WRAP_R,vtkgl::CLAMP_TO_EDGE); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_WRAP_S,vtkgl::CLAMP_TO_EDGE); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_WRAP_T,vtkgl::CLAMP_TO_EDGE); GLfloat borderColor[4]={0.0,0.0,0.0,0.0}; glTexParameterfv(vtkgl::TEXTURE_3D,GL_TEXTURE_BORDER_COLOR, borderColor); glPixelTransferf(GL_ALPHA_SCALE,1.0); glPixelTransferf(GL_ALPHA_BIAS,0.0); glPixelStorei(GL_UNPACK_ALIGNMENT,1); if(!(textureExtent[1]-textureExtent[0]+cellFlag==dim[0])) { glPixelStorei(GL_UNPACK_ROW_LENGTH,dim[0]-cellFlag); } if(!(textureExtent[3]-textureExtent[2]+cellFlag==dim[1])) { glPixelStorei(vtkgl::UNPACK_IMAGE_HEIGHT_EXT, dim[1]-cellFlag); } void *dataPtr=scalars->GetVoidPointer( ((textureExtent[4]*(dim[1]-cellFlag)+textureExtent[2]) *(dim[0]-cellFlag)+textureExtent[0]) *scalars->GetNumberOfComponents()); vtkgl::TexImage3D(vtkgl::TEXTURE_3D, 0, internalFormat, textureSize[0],textureSize[1],textureSize[2], 0,format,type,dataPtr); // Restore the default values. glPixelStorei(GL_UNPACK_ROW_LENGTH,0); glPixelStorei(vtkgl::UNPACK_IMAGE_HEIGHT_EXT,0); glPixelTransferf(GL_ALPHA_SCALE,1.0); glPixelTransferf(GL_ALPHA_BIAS,0.0); this->LoadedCellFlag=cellFlag; i=0; while(i<6) { this->LoadedExtent[i]=textureExtent[i]; ++i; } double spacing[3]; double origin[3]; input->GetSpacing(spacing); input->GetOrigin(origin); int swapBounds[3]; swapBounds[0]=(spacing[0]<0); swapBounds[1]=(spacing[1]<0); swapBounds[2]=(spacing[2]<0); if(!this->LoadedCellFlag) // loaded extents represent points { // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2]; // in general, x=o+i*spacing. // if spacing is positive min extent match the min of the // bounding box // and the max extent match the max of the bounding box // if spacing is negative min extent match the max of the // bounding box // and the max extent match the min of the bounding box // if spacing is negative, we may have to rethink the equation // between real point and texture coordinate... this->LoadedBounds[0]=origin[0]+ static_cast(this->LoadedExtent[0+swapBounds[0]])*spacing[0]; this->LoadedBounds[2]=origin[1]+ static_cast(this->LoadedExtent[2+swapBounds[1]])*spacing[1]; this->LoadedBounds[4]=origin[2]+ static_cast(this->LoadedExtent[4+swapBounds[2]])*spacing[2]; this->LoadedBounds[1]=origin[0]+ static_cast(this->LoadedExtent[1-swapBounds[0]])*spacing[0]; this->LoadedBounds[3]=origin[1]+ static_cast(this->LoadedExtent[3-swapBounds[1]])*spacing[1]; this->LoadedBounds[5]=origin[2]+ static_cast(this->LoadedExtent[5-swapBounds[2]])*spacing[2]; } else // loaded extents represent cells { int wholeTextureExtent[6]; input->GetExtent(wholeTextureExtent); i=1; while(i<6) { wholeTextureExtent[i]--; i+=2; } i=0; while(i<3) { if(this->LoadedExtent[2*i]==wholeTextureExtent[2*i]) { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]; } else { this->LoadedBounds[2*i+swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i])+0.5)*spacing[i]; } if(this->LoadedExtent[2*i+1]==wholeTextureExtent[2*i+1]) { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+1.0)*spacing[i]; } else { this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ (static_cast(this->LoadedExtent[2*i+1])+0.5)*spacing[i]; } ++i; } } modified=true; } // if enough memory else { } } //load fail with out of memory else { } } // proxy ok else { // proxy failed } } else { // out of therical limitationa } } // if obsolete if(this->Loaded && (needUpdate || modified)) { glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameterf(vtkgl::TEXTURE_3D,GL_TEXTURE_MAG_FILTER, GL_NEAREST ); modified=true; } if(modified) { this->BuildTime.Modified(); } } double *GetLoadedBounds() { assert("pre: loaded" && this->Loaded); return this->LoadedBounds; } vtkIdType *GetLoadedExtent() { assert("pre: loaded" && this->Loaded); return this->LoadedExtent; } int GetLoadedCellFlag() { assert("pre: loaded" && this->Loaded); return this->LoadedCellFlag; } bool IsLoaded() { return this->Loaded; } protected: GLuint TextureId; vtkTimeStamp BuildTime; double LoadedBounds[6]; vtkIdType LoadedExtent[6]; int LoadedCellFlag; bool Loaded; }; //----------------------------------------------------------------------------- // Display the status of the current framebuffer on the standard output. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::CheckFrameBufferStatus() { GLenum status; status = vtkgl::CheckFramebufferStatusEXT(vtkgl::FRAMEBUFFER_EXT); switch(status) { case 0: cout << "call to vtkgl::CheckFramebufferStatusEXT generates an error." << endl; break; case vtkgl::FRAMEBUFFER_COMPLETE_EXT: break; case vtkgl::FRAMEBUFFER_UNSUPPORTED_EXT: cout << "framebuffer is unsupported" << endl; break; case vtkgl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: cout << "framebuffer has an attachment error"<DisplayFrameBufferAttachments(); // this->DisplayReadAndDrawBuffers(); } //----------------------------------------------------------------------------- vtkStdString vtkMitkOpenGLGPUVolumeRayCastMapper::BufferToString(int buffer) { vtkStdString result; vtksys_ios::ostringstream ost; GLint size; GLint b=static_cast(buffer); switch(b) { case GL_NONE: ost << "GL_NONE"; break; case GL_FRONT_LEFT: ost << "GL_FRONT_LEFT"; break; case GL_FRONT_RIGHT: ost << "GL_FRONT_RIGHT"; break; case GL_BACK_LEFT: ost << "GL_BACK_LEFT"; break; case GL_BACK_RIGHT: ost << "GL_BACK_RIGHT"; break; case GL_FRONT: ost << "GL_FRONT"; break; case GL_BACK: ost << "GL_BACK"; break; case GL_LEFT: ost << "GL_LEFT"; break; case GL_RIGHT: ost << "GL_RIGHT"; break; case GL_FRONT_AND_BACK: ost << "GL_FRONT_AND_BACK"; break; default: glGetIntegerv(GL_AUX_BUFFERS,&size); if(buffer>=GL_AUX0 && buffer<(GL_AUX0+size)) { ost << "GL_AUX" << (buffer-GL_AUX0); } else { glGetIntegerv(vtkgl::MAX_COLOR_ATTACHMENTS_EXT,&size); if(static_cast(buffer)>=vtkgl::COLOR_ATTACHMENT0_EXT && static_cast(buffer)< (vtkgl::COLOR_ATTACHMENT0_EXT+static_cast(size))) { ost << "GL_COLOR_ATTACHMENT" << (static_cast(buffer)-vtkgl::COLOR_ATTACHMENT0_EXT) << "_EXT"; } else { ost << "unknown color buffer type=0x"<(value); vtkStdString s; GLenum i=0; while(iBufferToString(static_cast(value)); cout << "draw buffer " << i << "=" << s << endl; ++i; } glGetIntegerv(GL_READ_BUFFER,&value); s=this->BufferToString(static_cast(value)); cout << "read buffer=" << s << endl; } // ---------------------------------------------------------------------------- // Description: // Display all the attachments of the current framebuffer object. // ---------------------------------------------------------------------------- // // ---------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::DisplayFrameBufferAttachments() { GLint framebufferBinding; glGetIntegerv(vtkgl::FRAMEBUFFER_BINDING_EXT,&framebufferBinding); this->PrintError("after getting FRAMEBUFFER_BINDING_EXT"); if(framebufferBinding==0) { cout<<"Current framebuffer is bind to the system one"<(value); this->PrintError("after getting MAX_COLOR_ATTACHMENTS_EXT"); GLenum i=0; while(iDisplayFrameBufferAttachment(vtkgl::COLOR_ATTACHMENT0_EXT+i); ++i; } cout<<"depth attachement :"<DisplayFrameBufferAttachment(vtkgl::DEPTH_ATTACHMENT_EXT); cout<<"stencil attachement :"<DisplayFrameBufferAttachment(vtkgl::STENCIL_ATTACHMENT_EXT); } } // ---------------------------------------------------------------------------- // Description: // Display a given attachment for the current framebuffer object. //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::DisplayFrameBufferAttachment( unsigned int uattachment) { GLenum attachment=static_cast(uattachment); GLint params; vtkgl::GetFramebufferAttachmentParameterivEXT( vtkgl::FRAMEBUFFER_EXT,attachment, vtkgl::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,¶ms); this->PrintError("after getting FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT"); switch(params) { case GL_NONE: cout<<" this attachment is empty"<PrintError("after getting FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT"); cout<<" this attachment is a texture with name: "<PrintError( "after getting FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT"); cout<<" its mipmap level is: "<PrintError( "after getting FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT"); if(params==0) { cout<<" this is not a cube map texture."<PrintError( "after getting FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT"); if(params==0) { cout<<" this is not 3D texture."<PrintError("after getting FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT"); cout<<" this attachment is a renderbuffer with name: "<(params)); this->PrintError( "after getting binding the current RENDERBUFFER_EXT to params"); vtkgl::GetRenderbufferParameterivEXT(vtkgl::RENDERBUFFER_EXT, vtkgl::RENDERBUFFER_WIDTH_EXT, ¶ms); this->PrintError("after getting RENDERBUFFER_WIDTH_EXT"); cout<<" renderbuffer width="<PrintError("after getting RENDERBUFFER_HEIGHT_EXT"); cout<<" renderbuffer height="<PrintError("after getting RENDERBUFFER_INTERNAL_FORMAT_EXT"); cout<<" renderbuffer internal format=0x"<< hex<PrintError("after getting RENDERBUFFER_RED_SIZE_EXT"); cout<<" renderbuffer actual resolution for the red component="<PrintError("after getting RENDERBUFFER_GREEN_SIZE_EXT"); cout<<" renderbuffer actual resolution for the green component="<PrintError("after getting RENDERBUFFER_BLUE_SIZE_EXT"); cout<<" renderbuffer actual resolution for the blue component="<PrintError("after getting RENDERBUFFER_ALPHA_SIZE_EXT"); cout<<" renderbuffer actual resolution for the alpha component="<PrintError("after getting RENDERBUFFER_DEPTH_SIZE_EXT"); cout<<" renderbuffer actual resolution for the depth component="<PrintError("after getting RENDERBUFFER_STENCIL_SIZE_EXT"); cout<<" renderbuffer actual resolution for the stencil component=" <(errorCode)) { case GL_NO_ERROR: result="No error"; break; case GL_INVALID_ENUM: result="Invalid enum"; break; case GL_INVALID_VALUE: result="Invalid value"; break; case GL_INVALID_OPERATION: result="Invalid operation"; break; case GL_STACK_OVERFLOW: result="stack overflow"; break; case GL_STACK_UNDERFLOW: result="stack underflow"; break; case GL_OUT_OF_MEMORY: result="out of memory"; break; case vtkgl::TABLE_TOO_LARGE: // GL_ARB_imaging result="Table too large"; break; case vtkgl::INVALID_FRAMEBUFFER_OPERATION_EXT: // GL_EXT_framebuffer_object, 310 result="invalid framebuffer operation ext"; break; case vtkgl::TEXTURE_TOO_LARGE_EXT: // GL_EXT_texture result="Texture too large"; break; default: result="unknown error"; } assert("post: result_exists" && result!=0); return result; } //----------------------------------------------------------------------------- // Display headerMessage on the standard output and the last OpenGL error // message if any. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::PrintError(const char *headerMessage) { GLenum errorCode=glGetError(); if(errorCode!=GL_NO_ERROR) { if ( headerMessage ) { cout<(errorCode)); cout<UnsupportedRequiredExtensions=0; this->OpenGLObjectsCreated=0; this->LoadExtensionsSucceeded=0; this->NumberOfFrameBuffers=0; this->m_BindMax = false; // up to 2 frame buffer 2D textures (left/right) // 1 dataset 3D texture // 1 colormap 1D texture // 1 opacitymap 1d texture // 1 grabbed depth buffer 2d texture int i=0; while(iTextureObjects[i]=0; ++i; } this->DepthRenderBufferObject=0; this->FrameBufferObject=0; for ( int j = 0; j < 8; j++ ) { for (i = 0; i < 3; i++ ) { this->BoundingBox[j][i] = 0.0; } } this->LastSize[0]=0; this->LastSize[1]=0; this->ReductionFactor = 1.0; this->Supports_GL_ARB_texture_float=0; this->SupportsPixelBufferObjects=0; i=0; while(i<3) { this->TempMatrix[i]=vtkMatrix4x4::New(); ++i; } this->ErrorLine=0; this->ErrorColumn=0; this->ErrorString=0; this->LastParallelProjection= vtkMitkOpenGLGPUVolumeRayCastMapperProjectionNotInitialized; this->LastRayCastMethod= vtkMitkOpenGLGPUVolumeRayCastMapperMethodNotInitialized; this->LastCroppingMode= vtkMitkOpenGLGPUVolumeRayCastMapperCroppingNotInitialized; this->LastComponent= vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotInitialized; this->LastShade=vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotInitialized; this->ClippedBoundingBox = NULL; this->SmallInput = NULL; this->MaxValueFrameBuffer=0; this->MaxValueFrameBuffer2=0; this->ReducedSize[0]=0; this->ReducedSize[1]=0; this->NumberOfCroppingRegions=0; this->PolyDataBoundingBox=0; this->Planes=0; this->NearPlane=0; this->Clip=0; this->Densify=0; this->InvVolumeMatrix=vtkMatrix4x4::New(); this->ScaleBiasProgramShader=0; this->UFrameBufferTexture=-1; this->UScale=-1; this->UBias=-1; this->SavedFrameBuffer=0; this->BoxSource=0; this->NoiseTexture=0; this->NoiseTextureSize=0; this->NoiseTextureId=0; this->IgnoreSampleDistancePerPixel=true; this->ScalarsTextures=new vtkMapDataArrayTextureId; this->MaskTextures=new vtkMapMaskTextureId; this->RGBTable=0; this->Mask1RGBTable=0; this->Mask2RGBTable=0; this->OpacityTables=0; this->CurrentScalar=0; this->CurrentMask=0; this->ActualSampleDistance=1.0; this->LastProgressEventTime=0.0; // date in seconds this->PreserveOrientation=true; } //----------------------------------------------------------------------------- // Destruct a vtkMitkOpenGLGPUVolumeRayCastMapper - clean up any memory used //----------------------------------------------------------------------------- vtkMitkOpenGLGPUVolumeRayCastMapper::~vtkMitkOpenGLGPUVolumeRayCastMapper() { if(this->UnsupportedRequiredExtensions!=0) { delete this->UnsupportedRequiredExtensions; this->UnsupportedRequiredExtensions=0; } int i=0; while(i<3) { this->TempMatrix[i]->Delete(); this->TempMatrix[i]=0; ++i; } if(this->ErrorString!=0) { delete[] this->ErrorString; this->ErrorString=0; } if ( this->SmallInput ) { this->SmallInput->UnRegister(this); } if(this->PolyDataBoundingBox!=0) { this->PolyDataBoundingBox->UnRegister(this); this->PolyDataBoundingBox=0; } if(this->Planes!=0) { this->Planes->UnRegister(this); this->Planes=0; } if(this->NearPlane!=0) { this->NearPlane->UnRegister(this); this->NearPlane=0; } if(this->Clip!=0) { this->Clip->UnRegister(this); this->Clip=0; } if(this->Densify!=0) { this->Densify->UnRegister(this); this->Densify=0; } if(this->BoxSource!=0) { this->BoxSource->UnRegister(this); this->BoxSource=0; } this->InvVolumeMatrix->UnRegister(this); this->InvVolumeMatrix=0; if(this->NoiseTexture!=0) { delete[] this->NoiseTexture; this->NoiseTexture=0; this->NoiseTextureSize=0; } if(this->ScalarsTextures!=0) { delete this->ScalarsTextures; this->ScalarsTextures=0; } if(this->MaskTextures!=0) { delete this->MaskTextures; this->MaskTextures=0; } } //----------------------------------------------------------------------------- // Based on hardware and properties, we may or may not be able to // render using 3D texture mapping. This indicates if 3D texture // mapping is supported by the hardware, and if the other extensions // necessary to support the specific properties are available. // //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::IsRenderSupported( vtkRenderWindow *window, vtkVolumeProperty *vtkNotUsed(property)) { window->MakeCurrent(); if(!this->LoadExtensionsSucceeded) { this->LoadExtensions(window); } if(!this->LoadExtensionsSucceeded) { vtkDebugMacro( "The following OpenGL extensions are required but not supported: " << (this->UnsupportedRequiredExtensions->Stream.str()).c_str()); return 0; } return 1; } //----------------------------------------------------------------------------- // Return if the required OpenGL extension `extensionName' is supported. // If not, its name is added to the string of unsupported but required // extensions. // \pre extensions_exist: extensions!=0 // \pre extensionName_exists: extensionName!=0 //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::TestRequiredExtension( vtkOpenGLExtensionManager *extensions, const char *extensionName) { assert("pre: extensions_exist" && extensions!=0); assert("pre: extensionName_exists" && extensionName!=0); int result=extensions->ExtensionSupported(extensionName); if(!result) { if(this->LoadExtensionsSucceeded) { this->UnsupportedRequiredExtensions->Stream<LoadExtensionsSucceeded=0; } else { this->UnsupportedRequiredExtensions->Stream<<", "<LoadExtensionsSucceeded will be set to 0 or 1 // - this->UnsupportedRequiredExtensions will have a message indicating // any failure codes //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::LoadExtensions( vtkRenderWindow *window) { // We may already have a string stream for the unsupported extensions // from the last time this method was called. If so, delete it. if(this->UnsupportedRequiredExtensions!=0) { delete this->UnsupportedRequiredExtensions; } // Create a string stream to hold the unsupported extensions so we can // report something meaningful back this->UnsupportedRequiredExtensions = new vtkUnsupportedRequiredExtensionsStringStream; // It does not work on Apple OS X Snow Leopard with nVidia. // There is a bug in the OpenGL driver with an error in the // Cg compiler about an infinite loop. #ifdef __APPLE__ this->LoadExtensionsSucceeded=0; return; #endif // Assume success this->LoadExtensionsSucceeded=1; const char *gl_vendor=reinterpret_cast(glGetString(GL_VENDOR)); /* if(strstr(gl_vendor,"ATI")!=0) { this->LoadExtensionsSucceeded=0; return; }*/ const char *gl_version=reinterpret_cast(glGetString(GL_VERSION)); if(strstr(gl_version,"Mesa")!=0) { // - GL_VENDOR cannot be used because it can be "Brian Paul" or // "Mesa project" // - GL_RENDERER cannot be used because it can be "Software Rasterizer" or // "Mesa X11" // - GL_VERSION is more robust. It has things like "2.0 Mesa 7.0.4" or // "2.1 Mesa 7.2" or "2.1 Mesa 7.3-devel" // Mesa does not work with multiple draw buffers: // "framebuffer has bad draw buffer" // "render clipped 1 ERROR (x506) invalid framebuffer operation ext" this->LoadExtensionsSucceeded=0; return; } // Create an extension manager vtkOpenGLExtensionManager *extensions=vtkOpenGLExtensionManager::New(); extensions->SetRenderWindow(window); // GL_ARB_draw_buffers requires OpenGL 1.3, so we must have OpenGL 1.3 // We don't need to check for some extensions that become part of OpenGL // core after 1.3. Among them: // - texture_3d is in core OpenGL since 1.2 // - texture_edge_clamp is in core OpenGL since 1.2 // (GL_SGIS_texture_edge_clamp or GL_EXT_texture_edge_clamp (nVidia) ) // - multitexture is in core OpenGL since 1.3 int supports_GL_1_3=extensions->ExtensionSupported("GL_VERSION_1_3"); int supports_GL_2_0=0; // No 1.3 support - give up if(!supports_GL_1_3) { this->LoadExtensionsSucceeded=0; this->UnsupportedRequiredExtensions->Stream<< " OpenGL 1.3 is required but not supported"; extensions->Delete(); return; } // Check for 2.0 support supports_GL_2_0=extensions->ExtensionSupported("GL_VERSION_2_0"); // Some extensions that are supported in 2.0, but if we don't // have 2.0 we'll need to check further int supports_shading_language_100 = 1; int supports_shader_objects = 1; int supports_fragment_shader = 1; int supports_texture_non_power_of_two = 1; int supports_draw_buffers = 1; if(!supports_GL_2_0) { supports_shading_language_100= extensions->ExtensionSupported("GL_ARB_shading_language_100"); supports_shader_objects= extensions->ExtensionSupported("GL_ARB_shader_objects"); supports_fragment_shader= extensions->ExtensionSupported("GL_ARB_fragment_shader"); supports_texture_non_power_of_two= extensions->ExtensionSupported("GL_ARB_texture_non_power_of_two"); supports_draw_buffers= extensions->ExtensionSupported("GL_ARB_draw_buffers"); } // We have to check for framebuffer objects int supports_GL_EXT_framebuffer_object= extensions->ExtensionSupported("GL_EXT_framebuffer_object" ); // Find out if we have OpenGL 1.4 support int supports_GL_1_4=extensions->ExtensionSupported("GL_VERSION_1_4"); // Find out if we have the depth texture ARB extension int supports_GL_ARB_depth_texture= extensions->ExtensionSupported("GL_ARB_depth_texture"); // Depth textures are support if we either have OpenGL 1.4 // or if the depth texture ARB extension is supported int supports_depth_texture = supports_GL_1_4 || supports_GL_ARB_depth_texture; // Now start adding messages to the UnsupportedRequiredExtensions string // Log message if shading language 100 is not supported if(!supports_shading_language_100) { this->UnsupportedRequiredExtensions->Stream<< " shading_language_100 (or OpenGL 2.0) is required but not supported"; this->LoadExtensionsSucceeded=0; } else { // We can query the GLSL version, we need >=1.20 const char *glsl_version= reinterpret_cast(glGetString(vtkgl::SHADING_LANGUAGE_VERSION)); int glslMajor, glslMinor; vtksys_ios::istringstream ist(glsl_version); ist >> glslMajor; char c; ist.get(c); // '.' ist >> glslMinor; //sscanf(version, "%d.%d", &glslMajor, &glslMinor); if(glslMajor<1 || (glslMajor==1 && glslMinor<20)) { this->LoadExtensionsSucceeded=0; } } // Log message if shader objects are not supported if(!supports_shader_objects) { this->UnsupportedRequiredExtensions->Stream<< " shader_objects (or OpenGL 2.0) is required but not supported"; this->LoadExtensionsSucceeded=0; } // Log message if fragment shaders are not supported if(!supports_fragment_shader) { this->UnsupportedRequiredExtensions->Stream<< " fragment_shader (or OpenGL 2.0) is required but not supported"; this->LoadExtensionsSucceeded=0; } // Log message if non power of two textures are not supported if(!supports_texture_non_power_of_two) { this->UnsupportedRequiredExtensions->Stream<< " texture_non_power_of_two (or OpenGL 2.0) is required but not " << "supported"; this->LoadExtensionsSucceeded=0; } // Log message if draw buffers are not supported if(!supports_draw_buffers) { this->UnsupportedRequiredExtensions->Stream<< " draw_buffers (or OpenGL 2.0) is required but not supported"; this->LoadExtensionsSucceeded=0; } // Log message if depth textures are not supported if(!supports_depth_texture) { this->UnsupportedRequiredExtensions->Stream<< " depth_texture (or OpenGL 1.4) is required but not supported"; this->LoadExtensionsSucceeded=0; } // Log message if framebuffer objects are not supported if(!supports_GL_EXT_framebuffer_object) { this->UnsupportedRequiredExtensions->Stream<< " framebuffer_object is required but not supported"; this->LoadExtensionsSucceeded=0; } // Have we succeeded so far? If not, just return. if(!this->LoadExtensionsSucceeded) { extensions->Delete(); return; } // Now start loading the extensions // First load all 1.2 and 1.3 extensions (we know we // support at least up to 1.3) extensions->LoadExtension("GL_VERSION_1_2"); extensions->LoadExtension("GL_VERSION_1_3"); // Load the 2.0 extensions if supported if(supports_GL_2_0) { extensions->LoadExtension("GL_VERSION_2_0"); } // Otherwise, we'll need to specifically load the // shader objects, fragment shader, and draw buffers // extensions else { extensions->LoadCorePromotedExtension("GL_ARB_shader_objects"); extensions->LoadCorePromotedExtension("GL_ARB_fragment_shader"); extensions->LoadCorePromotedExtension("GL_ARB_draw_buffers"); } // Load the framebuffer object extension extensions->LoadExtension("GL_EXT_framebuffer_object"); // Optional extension (does not fail if not present) // Load it if supported which will allow us to store // textures as floats this->Supports_GL_ARB_texture_float= extensions->ExtensionSupported("GL_ARB_texture_float" ); if(this->Supports_GL_ARB_texture_float) { extensions->LoadExtension( "GL_ARB_texture_float" ); } // Optional extension (does not fail if not present) // Used to minimize memory footprint when loading large 3D textures // of scalars. // VBO or 1.5 is required by PBO or 2.1 int supports_GL_1_5=extensions->ExtensionSupported("GL_VERSION_1_5"); int supports_vertex_buffer_object=supports_GL_1_5 || extensions->ExtensionSupported("GL_ARB_vertex_buffer_object"); int supports_GL_2_1=extensions->ExtensionSupported("GL_VERSION_2_1"); this->SupportsPixelBufferObjects=supports_vertex_buffer_object && (supports_GL_2_1 || extensions->ExtensionSupported("GL_ARB_pixel_buffer_object")); if(this->SupportsPixelBufferObjects) { if(supports_GL_1_5) { extensions->LoadExtension("GL_VERSION_1_5"); } else { extensions->LoadCorePromotedExtension("GL_ARB_vertex_buffer_object"); } if(supports_GL_2_1) { extensions->LoadExtension("GL_VERSION_2_1"); } else { extensions->LoadCorePromotedExtension("GL_ARB_pixel_buffer_object"); } } // Ultimate test. Some old cards support OpenGL 2.0 but not while // statements in a fragment shader (example: nVidia GeForce FX 5200) // It does not fail when compiling each shader source but at linking // stage because the parser underneath only check for syntax during // compilation and the actual native code generation happens during // the linking stage. this->CreateGLSLObjects(); this->NumberOfCroppingRegions=1; this->BuildProgram(1,vtkMitkOpenGLGPUVolumeRayCastMapperMethodComposite, vtkMitkOpenGLGPUVolumeRayCastMapperShadeNo, vtkMitkOpenGLGPUVolumeRayCastMapperComponentOne); GLint params; vtkgl::GetProgramiv(static_cast(this->ProgramShader), vtkgl::LINK_STATUS,¶ms); if(params==GL_FALSE) { this->LoadExtensionsSucceeded=0; this->UnsupportedRequiredExtensions->Stream<< " this card does not support while statements in fragment shaders."; } // FB debug this->CheckLinkage(this->ProgramShader); // Release GLSL Objects. GLuint programShader=static_cast(this->ProgramShader); vtkgl::DeleteProgram(programShader); this->LastParallelProjection= vtkMitkOpenGLGPUVolumeRayCastMapperProjectionNotInitialized; this->LastRayCastMethod= vtkMitkOpenGLGPUVolumeRayCastMapperMethodNotInitialized; this->LastCroppingMode= vtkMitkOpenGLGPUVolumeRayCastMapperCroppingNotInitialized; this->LastComponent= vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotInitialized; this->LastShade=vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotInitialized; extensions->Delete(); } //----------------------------------------------------------------------------- // Create GLSL OpenGL objects such fragment program Ids. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::CreateGLSLObjects() { GLuint programShader; GLuint fragmentMainShader; programShader=vtkgl::CreateProgram(); fragmentMainShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::AttachShader(programShader,fragmentMainShader); vtkgl::DeleteShader(fragmentMainShader); // reference counting vtkgl::ShaderSource( fragmentMainShader,1, const_cast(&vtkMitkGPUVolumeRayCastMapper_HeaderFS),0); vtkgl::CompileShader(fragmentMainShader); this->CheckCompilation(static_cast(fragmentMainShader)); GLuint fragmentProjectionShader; GLuint fragmentTraceShader; GLuint fragmentCroppingShader; GLuint fragmentComponentShader; GLuint fragmentShadeShader; fragmentProjectionShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::AttachShader(programShader,fragmentProjectionShader); vtkgl::DeleteShader(fragmentProjectionShader); // reference counting fragmentTraceShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::AttachShader(programShader,fragmentTraceShader); vtkgl::DeleteShader(fragmentTraceShader); // reference counting fragmentCroppingShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::AttachShader(programShader,fragmentCroppingShader); vtkgl::DeleteShader(fragmentCroppingShader); // reference counting fragmentComponentShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); // don't delete it, it is optionally attached. fragmentShadeShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); // Save GL objects by static casting to standard C types. GL* types // are not allowed in VTK header files. this->ProgramShader=static_cast(programShader); this->FragmentMainShader=static_cast(fragmentMainShader); this->FragmentProjectionShader= static_cast(fragmentProjectionShader); this->FragmentTraceShader=static_cast(fragmentTraceShader); this->FragmentCroppingShader= static_cast(fragmentCroppingShader); this->FragmentComponentShader= static_cast(fragmentComponentShader); this->FragmentShadeShader= static_cast(fragmentShadeShader); } void vtkMitkOpenGLGPUVolumeRayCastMapper::BindFramebuffer() { vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront], 0); GLenum err = glGetError(); if(m_BindMax) { vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D,this->MaxValueFrameBuffer,0); } } //----------------------------------------------------------------------------- // Create OpenGL objects such as textures, buffers and fragment program Ids. // It only registers Ids, there is no actual initialization of textures or // fragment program. // // Pre-conditions: // This method assumes that this->LoadedExtensionsSucceeded is 1. // // Post-conditions: // When this method completes successfully, this->OpenGLObjectsCreated // will be 1. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::CreateOpenGLObjects() { // Do nothing if the OpenGL objects have already been created if ( this->OpenGLObjectsCreated ) { return; } // We need only two color buffers (ping-pong) this->NumberOfFrameBuffers=2; // TODO: clean this up! // 2*Frame buffers(2d textures)+colorMap (1d texture) +dataset (3d texture) // + opacitymap (1d texture) + grabbed depthMap (2d texture) // Frame buffers(2d textures)+colorMap (1d texture) +dataset (3d texture) // + opacity (1d texture)+grabbed depth buffer (2d texture) GLuint frameBufferObject; GLuint depthRenderBufferObject; GLuint textureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperNumberOfTextureObjects]; // Create the various objects we will need - one frame buffer // which will contain a render buffer for depth and a texture // for color. vtkgl::GenFramebuffersEXT(1, &frameBufferObject); // color vtkgl::GenRenderbuffersEXT(1, &depthRenderBufferObject); // depth glGenTextures(vtkMitkOpenGLGPUVolumeRayCastMapperNumberOfTextureObjects,textureObjects); // Color buffers GLint value; glGetIntegerv(vtkgl::FRAMEBUFFER_BINDING_EXT,&value); GLuint savedFrameBuffer=static_cast(value); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT,frameBufferObject); // Depth buffer vtkgl::BindRenderbufferEXT(vtkgl::RENDERBUFFER_EXT, depthRenderBufferObject); vtkgl::FramebufferRenderbufferEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::DEPTH_ATTACHMENT_EXT, vtkgl::RENDERBUFFER_EXT, depthRenderBufferObject); // Restore default frame buffer. vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT,savedFrameBuffer); this->CreateGLSLObjects(); // Save GL objects by static casting to standard C types. GL* types // are not allowed in VTK header files. this->FrameBufferObject=static_cast(frameBufferObject); this->DepthRenderBufferObject=static_cast(depthRenderBufferObject); int i=0; while(iTextureObjects[i]=static_cast(textureObjects[i]); ++i; } this->OpenGLObjectsCreated=1; } //----------------------------------------------------------------------------- // Check the compilation status of some fragment shader source. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::CheckCompilation( unsigned int fragmentShader) { GLuint fs=static_cast(fragmentShader); GLint params; vtkgl::GetShaderiv(fs,vtkgl::COMPILE_STATUS,¶ms); if(params==GL_TRUE) { vtkDebugMacro(<<"shader source compiled successfully"); } else { vtkErrorMacro(<<"shader source compile error"); // include null terminator vtkgl::GetShaderiv(fs,vtkgl::INFO_LOG_LENGTH,¶ms); if(params>0) { char *buffer=new char[params]; vtkgl::GetShaderInfoLog(fs,params,0,buffer); vtkErrorMacro(<<"log: "<(programShader); // info about the list of active uniform variables vtkgl::GetProgramiv(prog,vtkgl::ACTIVE_UNIFORMS,¶ms); cout<<"There are "<(params); vtkgl::GetProgramiv(prog,vtkgl::OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, ¶ms); GLint buffSize=params; char *name=new char[buffSize+1]; GLint size; GLenum type; while(i(programShader); vtkgl::GetProgramiv(prog,vtkgl::LINK_STATUS,¶ms); int status = 0; if(params==GL_TRUE) { status = 1; vtkDebugMacro(<<"program linked successfully"); } else { vtkErrorMacro(<<"program link error"); vtkgl::GetProgramiv(prog,vtkgl::INFO_LOG_LENGTH,¶ms); if(params>0) { char *buffer=new char[params]; vtkgl::GetProgramInfoLog(prog,params,0,buffer); vtkErrorMacro(<<"log: "<OpenGLObjectsCreated==0 //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::ReleaseGraphicsResources( vtkWindow *window) { if(this->OpenGLObjectsCreated) { window->MakeCurrent(); this->LastSize[0]=0; this->LastSize[1]=0; GLuint frameBufferObject=static_cast(this->FrameBufferObject); vtkgl::DeleteFramebuffersEXT(1,&frameBufferObject); GLuint depthRenderBufferObject= static_cast(this->DepthRenderBufferObject); vtkgl::DeleteRenderbuffersEXT(1,&depthRenderBufferObject); GLuint textureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperNumberOfTextureObjects]; int i=0; while(i<(vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+this->NumberOfFrameBuffers)) { textureObjects[i]=static_cast(this->TextureObjects[i]); ++i; } glDeleteTextures(vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+this->NumberOfFrameBuffers,textureObjects); if(this->MaxValueFrameBuffer!=0) { GLuint maxValueFrameBuffer= static_cast(this->MaxValueFrameBuffer); glDeleteTextures(1,&maxValueFrameBuffer); this->MaxValueFrameBuffer=0; } if(this->MaxValueFrameBuffer2!=0) { GLuint maxValueFrameBuffer2= static_cast(this->MaxValueFrameBuffer2); glDeleteTextures(1,&maxValueFrameBuffer2); this->MaxValueFrameBuffer2=0; } GLuint programShader=static_cast(this->ProgramShader); vtkgl::DeleteProgram(programShader); this->ProgramShader=0; GLuint fragmentComponentShader= static_cast(this->FragmentComponentShader); vtkgl::DeleteShader(fragmentComponentShader); GLuint fragmentShadeShader= static_cast(this->FragmentShadeShader); vtkgl::DeleteShader(fragmentShadeShader); GLuint scaleBiasProgramShader= static_cast(this->ScaleBiasProgramShader); if(scaleBiasProgramShader!=0) { vtkgl::DeleteProgram(scaleBiasProgramShader); this->ScaleBiasProgramShader=0; } this->LastParallelProjection= vtkMitkOpenGLGPUVolumeRayCastMapperProjectionNotInitialized; this->LastRayCastMethod= vtkMitkOpenGLGPUVolumeRayCastMapperMethodNotInitialized; this->LastCroppingMode= vtkMitkOpenGLGPUVolumeRayCastMapperCroppingNotInitialized; this->LastComponent= vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotInitialized; this->LastShade=vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotInitialized; this->OpenGLObjectsCreated=0; } if(this->NoiseTextureId!=0) { window->MakeCurrent(); GLuint noiseTextureObjects=static_cast(this->NoiseTextureId); glDeleteTextures(1,&noiseTextureObjects); this->NoiseTextureId=0; } if(this->ScalarsTextures!=0) { if(!this->ScalarsTextures->Map.empty()) { vtkstd::map::iterator it=this->ScalarsTextures->Map.begin(); while(it!=this->ScalarsTextures->Map.end()) { vtkKWScalarField *texture=(*it).second; delete texture; ++it; } this->ScalarsTextures->Map.clear(); } } if(this->MaskTextures!=0) { if(!this->MaskTextures->Map.empty()) { vtkstd::map::iterator it=this->MaskTextures->Map.begin(); while(it!=this->MaskTextures->Map.end()) { vtkKWMask *texture=(*it).second; delete texture; ++it; } this->MaskTextures->Map.clear(); } } if(this->RGBTable!=0) { delete this->RGBTable; this->RGBTable=0; } if(this->Mask1RGBTable!=0) { delete this->Mask1RGBTable; this->Mask1RGBTable=0; } if(this->Mask2RGBTable!=0) { delete this->Mask2RGBTable; this->Mask2RGBTable=0; } if(this->OpacityTables!=0) { delete this->OpacityTables; this->OpacityTables=0; } } //----------------------------------------------------------------------------- // Allocate memory on the GPU for the framebuffers according to the size of // the window or reallocate if the size has changed. Return true if // allocation succeeded. // \pre ren_exists: ren!=0 // \pre opengl_objects_created: this->OpenGLObjectsCreated // \post right_size: LastSize[]=window size. //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::AllocateFrameBuffers(vtkRenderer *ren) { assert("pre: ren_exists" && ren!=0); assert("pre: opengl_objects_created" && this->OpenGLObjectsCreated); int result=1; int size[2]; ren->GetTiledSize(&size[0],&size[1]); int sizeChanged=this->LastSize[0]!=size[0] || this->LastSize[1]!=size[1]; GLenum errorCode=glGetError(); // Need allocation? if(sizeChanged) { int i=0; GLenum errorCode=glGetError(); while(i NumberOfFrameBuffers && errorCode==GL_NO_ERROR) { glBindTexture(GL_TEXTURE_2D,static_cast(this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+i])); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Here we are assuming that GL_ARB_texture_non_power_of_two is available if(this->Supports_GL_ARB_texture_float) { glTexImage2D(GL_TEXTURE_2D,0,vtkgl::RGBA16F_ARB,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } else { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } errorCode=glGetError(); ++i; } if(errorCode==GL_NO_ERROR) { // grabbed depth buffer glBindTexture(GL_TEXTURE_2D,static_cast(this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectDepthMap])); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D, vtkgl::DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexImage2D(GL_TEXTURE_2D, 0, vtkgl::DEPTH_COMPONENT32, size[0],size[1], 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL ); // Set up the depth render buffer GLint savedFrameBuffer; glGetIntegerv(vtkgl::FRAMEBUFFER_BINDING_EXT,&savedFrameBuffer); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(this->FrameBufferObject)); this->BindFramebuffer(); vtkgl::BindRenderbufferEXT( vtkgl::RENDERBUFFER_EXT, static_cast(this->DepthRenderBufferObject)); vtkgl::RenderbufferStorageEXT(vtkgl::RENDERBUFFER_EXT, vtkgl::DEPTH_COMPONENT24,size[0],size[1]); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(savedFrameBuffer)); errorCode=glGetError(); if(errorCode==GL_NO_ERROR) { this->LastSize[0]=size[0]; this->LastSize[1]=size[1]; } } result=errorCode==GL_NO_ERROR; } int needNewMaxValueBuffer=this->MaxValueFrameBuffer==0 && (this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND); if(needNewMaxValueBuffer) { // blend mode changed and need max value buffer. // create and bind second color buffer (we use only the red component // to store the max scalar). We cant use a one component color buffer // because all color buffer have to have the same format. // max scalar frame buffer GLuint maxValueFrameBuffer; glGenTextures(1,&maxValueFrameBuffer); this->MaxValueFrameBuffer= static_cast(maxValueFrameBuffer); // Color buffers this->m_BindMax = true; // max scalar frame buffer2 GLuint maxValueFrameBuffer2; glGenTextures(1,&maxValueFrameBuffer2); glBindTexture(GL_TEXTURE_2D,maxValueFrameBuffer2); this->MaxValueFrameBuffer2= static_cast(maxValueFrameBuffer2); } else { if(this->MaxValueFrameBuffer!=0 && (this->BlendMode!=vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND && this->BlendMode!=vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND)) { // blend mode changed and does not need max value buffer anymore. GLint savedFrameBuffer; glGetIntegerv(vtkgl::FRAMEBUFFER_BINDING_EXT,&savedFrameBuffer); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(this->FrameBufferObject)); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D,0,0); // not scalar buffer vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(savedFrameBuffer)); GLuint maxValueFrameBuffer= static_cast(this->MaxValueFrameBuffer); glDeleteTextures(1,&maxValueFrameBuffer); this->MaxValueFrameBuffer=0; m_BindMax = false; GLuint maxValueFrameBuffer2= static_cast(this->MaxValueFrameBuffer2); glDeleteTextures(1,&maxValueFrameBuffer2); this->MaxValueFrameBuffer2=0; } } if((this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) && (sizeChanged || needNewMaxValueBuffer)) { // max scalar frame buffer GLuint maxValueFrameBuffer=static_cast(this->MaxValueFrameBuffer); glBindTexture(GL_TEXTURE_2D,maxValueFrameBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Here we are assuming that GL_ARB_texture_non_power_of_two is available if(this->Supports_GL_ARB_texture_float) { glTexImage2D(GL_TEXTURE_2D,0,vtkgl::RGBA16F_ARB,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } else { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } // max scalar frame buffer 2 GLuint maxValueFrameBuffer2=static_cast(this->MaxValueFrameBuffer2); glBindTexture(GL_TEXTURE_2D,maxValueFrameBuffer2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Here we are assuming that GL_ARB_texture_non_power_of_two is available if(this->Supports_GL_ARB_texture_float) { glTexImage2D(GL_TEXTURE_2D,0,vtkgl::RGBA16F_ARB,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } else { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16,size[0],size[1], 0, GL_RGBA, GL_FLOAT, NULL ); } } PrintError("AllocateFrameBuffers"); return result; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::GetTextureFormat( vtkImageData *input, unsigned int *internalFormat, unsigned int *format, unsigned int *type, int *componentSize) { *internalFormat=0; *format=0; *type=0; *componentSize=0; vtkDataArray *scalars=this->GetScalars(input,this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); int scalarType=scalars->GetDataType(); int components=scalars->GetNumberOfComponents(); *componentSize=vtkAbstractArray::GetDataTypeSize(scalarType)*components; if(components==4) { // this is RGBA, unsigned char only *internalFormat=GL_RGBA16; *format=GL_RGBA; *type=GL_UNSIGNED_BYTE; } else { // components==1 switch(scalarType) { case VTK_FLOAT: if(this->Supports_GL_ARB_texture_float) { *internalFormat=vtkgl::INTENSITY16F_ARB; } else { *internalFormat=GL_INTENSITY16; } *format=GL_RED; *type=GL_FLOAT; break; case VTK_UNSIGNED_CHAR: *internalFormat=GL_INTENSITY8; *format=GL_RED; *type=GL_UNSIGNED_BYTE; break; case VTK_SIGNED_CHAR: *internalFormat=GL_INTENSITY8; *format=GL_RED; *type=GL_BYTE; break; case VTK_CHAR: // not supported assert("check: impossible case" && 0); break; case VTK_BIT: // not supported assert("check: impossible case" && 0); break; case VTK_ID_TYPE: // not supported assert("check: impossible case" && 0); break; case VTK_INT: *internalFormat=GL_INTENSITY16; *format=GL_RED; *type=GL_INT; break; case VTK_DOUBLE: case VTK___INT64: case VTK_LONG: case VTK_LONG_LONG: case VTK_UNSIGNED___INT64: case VTK_UNSIGNED_LONG: case VTK_UNSIGNED_LONG_LONG: if(this->Supports_GL_ARB_texture_float) { *internalFormat=vtkgl::INTENSITY16F_ARB; } else { *internalFormat=GL_INTENSITY16; } *format=GL_RED; *type=GL_FLOAT; break; case VTK_SHORT: *internalFormat=GL_INTENSITY16; *format=GL_RED; *type=GL_SHORT; break; case VTK_STRING: // not supported assert("check: impossible case" && 0); break; case VTK_UNSIGNED_SHORT: *internalFormat=GL_INTENSITY16; *format=GL_RED; *type=GL_UNSIGNED_SHORT; break; case VTK_UNSIGNED_INT: *internalFormat=GL_INTENSITY16; *format=GL_RED; *type=GL_UNSIGNED_INT; break; default: assert("check: impossible case" && 0); break; } } } //----------------------------------------------------------------------------- // Assuming the textureSize[3] is less of equal to the maximum size of an // OpenGL 3D texture, try to see if the texture can fit on the card. //----------------------------------------------------------------------------- bool vtkMitkOpenGLGPUVolumeRayCastMapper::TestLoadingScalar( unsigned int internalFormat, unsigned int format, unsigned int type, int textureSize[3], int componentSize) { // componentSize=vtkAbstractArray::GetDataTypeSize(scalarType)*input->GetNumberOfScalarComponents() bool result; vtkgl::TexImage3D(vtkgl::PROXY_TEXTURE_3D,0, static_cast(internalFormat), textureSize[0],textureSize[1],textureSize[2],0, format, type,0); GLint width; glGetTexLevelParameteriv(vtkgl::PROXY_TEXTURE_3D,0,GL_TEXTURE_WIDTH, &width); result=width!=0; if(result) { // so far, so good but some cards always succeed with a proxy texture // let's try to actually allocate.. vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,static_cast(internalFormat), textureSize[0], textureSize[1],textureSize[2],0, format, type,0); GLenum errorCode=glGetError(); result=errorCode!=GL_OUT_OF_MEMORY; if(result) { if(errorCode!=GL_NO_ERROR) { cout<<"after try to load the texture"; cout<<" ERROR (x"<(errorCode)); cout<(this->MaxMemoryInBytes)*this->MaxMemoryFraction; } } return result; } //----------------------------------------------------------------------------- // Load the scalar field (one or four component scalar field), cell or point // based for a given subextent of the whole extent (can be the whole extent) // as a 3D texture on the GPU. // Extents are expressed in point if the cell flag is false or in cells of // the cell flag is true. // It returns true if it succeeded, false if there is not enough memory on // the GPU. // If succeeded, it updates the LoadedExtent, LoadedBounds, LoadedCellFlag // and LoadedTime. It also succeed if the scalar field is already loaded // (ie since last load, input has not changed and cell flag has not changed // and requested texture extents are enclosed in the loaded extent). // \pre input_exists: input!=0 // \pre valid_point_extent: (this->CellFlag || // (textureExtent[0]CellFlag || // (textureExtent[0]<=textureExtent[1] && // textureExtent[2]<=textureExtent[3] && // textureExtent[4]<=textureExtent[5]))) //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::LoadScalarField(vtkImageData *input, vtkImageData *maskInput, int textureExtent[6], vtkVolume *volume) { assert("pre: input_exists" && input!=0); assert("pre: valid_point_extent" && (this->CellFlag || (textureExtent[0]CellFlag || (textureExtent[0]<=textureExtent[1] && textureExtent[2]<=textureExtent[3] && textureExtent[4]<=textureExtent[5]))); int result=1; // succeeded // make sure we rebind our texture object to texture0 even if we don't have // to load the data themselves because the binding might be changed by // another mapper between two rendering calls. vtkgl::ActiveTexture(vtkgl::TEXTURE0); // Find the texture. vtkstd::map::iterator it= this->ScalarsTextures->Map.find(input); vtkKWScalarField *texture; if(it==this->ScalarsTextures->Map.end()) { texture=new vtkKWScalarField; this->ScalarsTextures->Map[input]=texture; texture->SetSupports_GL_ARB_texture_float(this->Supports_GL_ARB_texture_float==1); } else { texture=(*it).second; } texture->Update(input,this->CellFlag,textureExtent,this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, volume->GetProperty()->GetInterpolationType() ==VTK_LINEAR_INTERPOLATION, this->TableRange, static_cast(static_cast(this->MaxMemoryInBytes)*this->MaxMemoryFraction)); result=texture->IsLoaded(); this->CurrentScalar=texture; // Mask if(maskInput!=0) { vtkgl::ActiveTexture(vtkgl::TEXTURE7); // Find the texture. vtkstd::map::iterator it2= this->MaskTextures->Map.find(maskInput); vtkKWMask *mask; if(it2==this->MaskTextures->Map.end()) { mask=new vtkKWMask; this->MaskTextures->Map[maskInput]=mask; } else { mask=(*it2).second; } mask->Update(maskInput,this->CellFlag,textureExtent,this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, static_cast(static_cast(this->MaxMemoryInBytes)*this->MaxMemoryFraction)); result=result && mask->IsLoaded(); this->CurrentMask=mask; vtkgl::ActiveTexture(vtkgl::TEXTURE0); } return result; } //----------------------------------------------------------------------------- // Allocate memory and load color table on the GPU or // reload it if the transfer function changed. // \pre vol_exists: vol!=0 // \pre valid_numberOfScalarComponents: numberOfScalarComponents==1 || numberOfScalarComponents==4 //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::UpdateColorTransferFunction( vtkVolume *vol, int numberOfScalarComponents) { assert("pre: vol_exists" && vol!=0); assert("pre: valid_numberOfScalarComponents" && (numberOfScalarComponents==1 || numberOfScalarComponents==4)); // Build the colormap in a 1D texture. // 1D RGB-texture=mapping from scalar values to color values // build the table if(numberOfScalarComponents==1) { vtkVolumeProperty *volumeProperty=vol->GetProperty(); vtkColorTransferFunction *colorTransferFunction=volumeProperty->GetRGBTransferFunction(0); vtkgl::ActiveTexture(vtkgl::TEXTURE1); this->RGBTable->Update( colorTransferFunction,this->TableRange, volumeProperty->GetInterpolationType()==VTK_LINEAR_INTERPOLATION); // Restore default vtkgl::ActiveTexture( vtkgl::TEXTURE0); } if(this->MaskInput!=0) { vtkVolumeProperty *volumeProperty=vol->GetProperty(); vtkColorTransferFunction *c=volumeProperty->GetRGBTransferFunction(1); vtkgl::ActiveTexture(vtkgl::TEXTURE8); this->Mask1RGBTable->Update(c,this->TableRange,false); c=volumeProperty->GetRGBTransferFunction(2); vtkgl::ActiveTexture(vtkgl::TEXTURE9); this->Mask2RGBTable->Update(c,this->TableRange,false); // Restore default vtkgl::ActiveTexture( vtkgl::TEXTURE0); } return 1; } //----------------------------------------------------------------------------- // Allocate memory and load opacity table on the GPU or // reload it if the transfert function changed. // \pre vol_exists: vol!=0 // \pre valid_numberOfScalarComponents: numberOfScalarComponents==1 || numberOfScalarComponents==4 //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::UpdateOpacityTransferFunction( vtkVolume *vol, int numberOfScalarComponents, unsigned int level) { assert("pre: vol_exists" && vol!=0); assert("pre: valid_numberOfScalarComponents" && (numberOfScalarComponents==1 || numberOfScalarComponents==4)); (void)numberOfScalarComponents; // remove warning in release mode. vtkVolumeProperty *volumeProperty=vol->GetProperty(); vtkPiecewiseFunction *scalarOpacity=volumeProperty->GetScalarOpacity(); vtkgl::ActiveTexture( vtkgl::TEXTURE2); //stay here this->OpacityTables->Vector[level].Update( scalarOpacity,this->BlendMode, this->ActualSampleDistance, this->TableRange, volumeProperty->GetScalarOpacityUnitDistance(0), volumeProperty->GetInterpolationType()==VTK_LINEAR_INTERPOLATION); // Restore default active texture vtkgl::ActiveTexture( vtkgl::TEXTURE0); return 1; } //----------------------------------------------------------------------------- // Prepare rendering in the offscreen framebuffer. // \pre ren_exists: ren!=0 // \pre vol_exists: vol!=0 //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::SetupRender(vtkRenderer *ren, vtkVolume *vol) { assert("pre: ren_exists" && ren!=0); assert("pre: vol_exists" && vol!=0); double aspect[2]; int lowerLeft[2]; int usize, vsize; ren->GetTiledSizeAndOrigin(&usize,&vsize,lowerLeft,lowerLeft+1); usize = static_cast(usize*this->ReductionFactor); vsize = static_cast(vsize*this->ReductionFactor); this->ReducedSize[0]=usize; this->ReducedSize[1]=vsize; // the FBO has the size of the renderer (not the renderwindow), // we always starts at 0,0. glViewport(0,0, usize, vsize); glEnable( GL_SCISSOR_TEST ); // scissor on the FBO, on the reduced part. glScissor(0,0, usize, vsize); glClearColor(0.0, 0.0, 0.0, 0.0); // maxvalue is 1 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ren->ComputeAspect(); ren->GetAspect(aspect); double aspect2[2]; ren->vtkViewport::ComputeAspect(); ren->vtkViewport::GetAspect(aspect2); double aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]); vtkCamera *cam = ren->GetActiveCamera(); glMatrixMode( GL_PROJECTION); if(usize && vsize) { this->TempMatrix[0]->DeepCopy(cam->GetProjectionTransformMatrix( aspectModification*usize/vsize, -1,1)); this->TempMatrix[0]->Transpose(); glLoadMatrixd(this->TempMatrix[0]->Element[0]); } else { glLoadIdentity(); } // push the model view matrix onto the stack, make sure we // adjust the mode first glMatrixMode(GL_MODELVIEW); glPushMatrix(); this->TempMatrix[0]->DeepCopy(vol->GetMatrix()); this->TempMatrix[0]->Transpose(); // insert camera view transformation glMultMatrixd(this->TempMatrix[0]->Element[0]); glShadeModel(GL_SMOOTH); glDisable( GL_LIGHTING); glEnable (GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); // very important, otherwise the first image looks dark. this->PrintError("SetupRender"); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::DebugDisplayBox(vtkPolyData *box) { vtkPoints *points=box->GetPoints(); vtkCellArray *polys=box->GetPolys(); cout<<"npts="<GetNumberOfPoints()<GetNumberOfPoints()) { double coords[3]; points->GetPoint(pointId,coords); cout<<"pointId="<GetMatrix( this->InvVolumeMatrix ); this->InvVolumeMatrix->Invert(); if(this->BoxSource==0) { this->BoxSource=vtkTessellatedBoxSource::New(); } this->BoxSource->SetBounds(worldBounds); this->BoxSource->SetLevel(0); this->BoxSource->QuadsOn(); if(this->Planes==0) { this->Planes=vtkPlaneCollection::New(); } this->Planes->RemoveAllItems(); vtkCamera *cam = ren->GetActiveCamera(); double camWorldRange[2]; double camWorldPos[4]; double camFocalWorldPoint[4]; double camWorldDirection[3]; double range[2]; double camPos[4]; double focalPoint[4]; double direction[3]; cam->GetPosition(camWorldPos); camWorldPos[3] = 1.0; this->InvVolumeMatrix->MultiplyPoint( camWorldPos, camPos ); if ( camPos[3] ) { camPos[0] /= camPos[3]; camPos[1] /= camPos[3]; camPos[2] /= camPos[3]; } cam->GetFocalPoint(camFocalWorldPoint); camFocalWorldPoint[3]=1.0; this->InvVolumeMatrix->MultiplyPoint( camFocalWorldPoint,focalPoint ); if ( focalPoint[3] ) { focalPoint[0] /= focalPoint[3]; focalPoint[1] /= focalPoint[3]; focalPoint[2] /= focalPoint[3]; } // Compute the normalized view direction direction[0] = focalPoint[0] - camPos[0]; direction[1] = focalPoint[1] - camPos[1]; direction[2] = focalPoint[2] - camPos[2]; vtkMath::Normalize(direction); // The range (near/far) must also be transformed // into the local coordinate system. camWorldDirection[0] = camFocalWorldPoint[0] - camWorldPos[0]; camWorldDirection[1] = camFocalWorldPoint[1] - camWorldPos[1]; camWorldDirection[2] = camFocalWorldPoint[2] - camWorldPos[2]; vtkMath::Normalize(camWorldDirection); double camNearWorldPoint[4]; double camFarWorldPoint[4]; double camNearPoint[4]; double camFarPoint[4]; cam->GetClippingRange(camWorldRange); camNearWorldPoint[0] = camWorldPos[0] + camWorldRange[0]*camWorldDirection[0]; camNearWorldPoint[1] = camWorldPos[1] + camWorldRange[0]*camWorldDirection[1]; camNearWorldPoint[2] = camWorldPos[2] + camWorldRange[0]*camWorldDirection[2]; camNearWorldPoint[3] = 1.; camFarWorldPoint[0] = camWorldPos[0] + camWorldRange[1]*camWorldDirection[0]; camFarWorldPoint[1] = camWorldPos[1] + camWorldRange[1]*camWorldDirection[1]; camFarWorldPoint[2] = camWorldPos[2] + camWorldRange[1]*camWorldDirection[2]; camFarWorldPoint[3] = 1.; this->InvVolumeMatrix->MultiplyPoint( camNearWorldPoint, camNearPoint ); if (camNearPoint[3]) { camNearPoint[0] /= camNearPoint[3]; camNearPoint[1] /= camNearPoint[3]; camNearPoint[2] /= camNearPoint[3]; } this->InvVolumeMatrix->MultiplyPoint( camFarWorldPoint, camFarPoint ); if (camFarPoint[3]) { camFarPoint[0] /= camFarPoint[3]; camFarPoint[1] /= camFarPoint[3]; camFarPoint[2] /= camFarPoint[3]; } range[0] = sqrt(vtkMath::Distance2BetweenPoints(camNearPoint, camPos)); range[1] = sqrt(vtkMath::Distance2BetweenPoints(camFarPoint, camPos)); //double nearPoint[3], farPoint[3]; double dist = range[1] - range[0]; range[0] += dist / (2<<16); range[1] -= dist / (2<<16); if(this->NearPlane==0) { this->NearPlane= vtkPlane::New(); } //this->NearPlane->SetOrigin( nearPoint ); this->NearPlane->SetOrigin( camNearPoint ); this->NearPlane->SetNormal( direction ); this->Planes->AddItem(this->NearPlane); if ( this->ClippingPlanes ) { this->ClippingPlanes->InitTraversal(); vtkPlane *plane; while ( (plane = this->ClippingPlanes->GetNextItem()) ) { // Planes are in world coordinates, we need to // convert them in local coordinates double planeOrigin[4], planeNormal[4], planeP1[4]; plane->GetOrigin(planeOrigin); planeOrigin[3] = 1.; plane->GetNormal(planeNormal); planeP1[0] = planeOrigin[0] + planeNormal[0]; planeP1[1] = planeOrigin[1] + planeNormal[1]; planeP1[2] = planeOrigin[2] + planeNormal[2]; planeP1[3] = 1.; this->InvVolumeMatrix->MultiplyPoint(planeOrigin, planeOrigin); this->InvVolumeMatrix->MultiplyPoint(planeP1, planeP1); if( planeOrigin[3]) { planeOrigin[0] /= planeOrigin[3]; planeOrigin[1] /= planeOrigin[3]; planeOrigin[2] /= planeOrigin[3]; } if( planeP1[3]) { planeP1[0] /= planeP1[3]; planeP1[1] /= planeP1[3]; planeP1[2] /= planeP1[3]; } planeNormal[0] = planeP1[0] - planeOrigin[0]; planeNormal[1] = planeP1[1] - planeOrigin[1]; planeNormal[2] = planeP1[2] - planeOrigin[2]; vtkMath::Normalize(planeNormal); vtkPlane* localPlane = vtkPlane::New(); localPlane->SetOrigin(planeOrigin); localPlane->SetNormal(planeNormal); this->Planes->AddItem(localPlane); localPlane->Delete(); } } if(this->Clip==0) { this->Clip=vtkClipConvexPolyData::New(); this->Clip->SetInputConnection(this->BoxSource->GetOutputPort()); this->Clip->SetPlanes( this->Planes ); } this->Clip->Update(); if(this->Densify==0) { this->Densify=vtkDensifyPolyData::New(); this->Densify->SetInputConnection(this->Clip->GetOutputPort()); this->Densify->SetNumberOfSubdivisions(2); } this->Densify->Update(); this->ClippedBoundingBox = this->Densify->GetOutput(); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::RenderClippedBoundingBox( int tcoordFlag, size_t currentBlock, size_t numberOfBlocks, vtkRenderWindow *renWin ) { assert("pre: valid_currentBlock" && currentBlockClippedBoundingBox->GetPoints(); vtkCellArray *polys = this->ClippedBoundingBox->GetPolys(); vtkIdType npts; vtkIdType *pts; vtkIdType i, j; double center[3] = {0,0,0}; double min[3] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX}; double max[3] = {VTK_DOUBLE_MIN, VTK_DOUBLE_MIN, VTK_DOUBLE_MIN}; // First compute center point npts = points->GetNumberOfPoints(); for ( i = 0; i < npts; i++ ) { double pt[3]; points->GetPoint( i, pt ); for ( j = 0; j < 3; j++ ) { min[j] = (pt[j]max[j])?(pt[j]):(max[j]); } } center[0] = 0.5*(min[0]+max[0]); center[1] = 0.5*(min[1]+max[1]); center[2] = 0.5*(min[2]+max[2]); double *loadedBounds=0; vtkIdType *loadedExtent=0; if ( tcoordFlag ) { loadedBounds=this->CurrentScalar->GetLoadedBounds(); loadedExtent=this->CurrentScalar->GetLoadedExtent(); } double *spacing=this->GetInput()->GetSpacing(); double spacingSign[3]; i=0; while(i<3) { if(spacing[i]<0) { spacingSign[i]=-1.0; } else { spacingSign[i]=1.0; } ++i; } // make it double for the ratio of the progress. int polyId=0; double polyCount=static_cast(polys->GetNumberOfCells()); polys->InitTraversal(); int abort=0; while ( !abort && polys->GetNextCell(npts, pts) ) { vtkIdType start, end, inc; // Need to have at least a triangle if ( npts > 2 ) { // Check the cross product of the first two // vectors dotted with the vector from the // center to the second point. Is it positive or // negative? double p1[3], p2[3], p3[3]; double v1[3], v2[3], v3[3], v4[3]; points->GetPoint(pts[0], p1 ); points->GetPoint(pts[1], p2 ); points->GetPoint(pts[2], p3 ); v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; v2[0] = p2[0] - p3[0]; v2[1] = p2[1] - p3[1]; v2[2] = p2[2] - p3[2]; vtkMath::Cross( v1, v2, v3 ); vtkMath::Normalize(v3); v4[0] = p2[0] - center[0]; v4[1] = p2[1] - center[1]; v4[2] = p2[2] - center[2]; vtkMath::Normalize(v4); double dot = vtkMath::Dot( v3, v4 ); if (( dot < 0) && this->PreserveOrientation) { start = 0; end = npts; inc = 1; } else { start = npts-1; end = -1; inc = -1; } glBegin( GL_TRIANGLE_FAN ); // GL_POLYGON -> GL_TRIANGLE_FAN double vert[3]; double tcoord[3]; for ( i = start; i != end; i += inc ) { points->GetPoint(pts[i], vert); if ( tcoordFlag ) { for ( j = 0; j < 3; j++ ) { // loaded bounds take both cell data and point date cases into // account if(this->CellFlag) // texcoords between 0 and 1. More complex // depends on the loaded texture { tcoord[j] = spacingSign[j]*(vert[j] - loadedBounds[j*2]) / (loadedBounds[j*2+1] - loadedBounds[j*2]); } else // texcoords between 1/2N and 1-1/2N. { double tmp; // between 0 and 1 tmp = spacingSign[j]*(vert[j] - loadedBounds[j*2]) / (loadedBounds[j*2+1] - loadedBounds[j*2]); double delta=static_cast( loadedExtent[j*2+1]-loadedExtent[j*2]+1); tcoord[j]=(tmp*(delta-1)+0.5)/delta; } } vtkgl::MultiTexCoord3dv(vtkgl::TEXTURE0, tcoord); } glVertex3dv(vert); } glEnd(); } if(tcoordFlag) { // otherwise, we are rendering back face to initialize the zbuffer. if (!this->GeneratingCanonicalView && this->ReportProgress) { glFinish(); // Only invoke an event at most one every second. double currentTime=vtkTimerLog::GetUniversalTime(); if(currentTime - this->LastProgressEventTime > 1.0) { double progress=(static_cast(currentBlock)+polyId/polyCount)/ static_cast(numberOfBlocks); this->InvokeEvent(vtkCommand::VolumeMapperRenderProgressEvent, &progress); renWin->MakeCurrent(); this->LastProgressEventTime = currentTime; } } abort=renWin->CheckAbortStatus(); } ++polyId; } return abort; } void vtkMitkOpenGLGPUVolumeRayCastMapper::CopyFBOToTexture() { // in OpenGL copy texture to texture does not exist but // framebuffer to texture exists (and our FB is an FBO). // we have to copy and not just to switch color textures because the // colorbuffer has to accumulate color or values step after step. // Switching would not work because two different steps can draw different // polygons that don't overlap vtkgl::ActiveTexture(vtkgl::TEXTURE4); glBindTexture( GL_TEXTURE_2D, this->TextureObjects[ vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+1]); glReadBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,this->ReducedSize[0], this->ReducedSize[1]); if(this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) { vtkgl::ActiveTexture(vtkgl::TEXTURE5); glBindTexture(GL_TEXTURE_2D,this->MaxValueFrameBuffer2); glReadBuffer(vtkgl::COLOR_ATTACHMENT0_EXT+1); glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,this->ReducedSize[0], this->ReducedSize[1]); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } //----------------------------------------------------------------------------- // Restore OpenGL state after rendering of the dataset. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::CleanupRender() { glPopMatrix(); glDisable(GL_CULL_FACE); } //----------------------------------------------------------------------------- // Build the fragment shader program that scale and bias a texture // for window/level purpose. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::BuildScaleBiasProgram() { if(this->ScaleBiasProgramShader==0) { GLuint programShader; GLuint fragmentShader; programShader=vtkgl::CreateProgram(); fragmentShader=vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::AttachShader(programShader,fragmentShader); vtkgl::DeleteShader(fragmentShader); // reference counting vtkgl::ShaderSource( fragmentShader,1, const_cast(&vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS),0); vtkgl::CompileShader(fragmentShader); this->CheckCompilation(static_cast(fragmentShader)); vtkgl::LinkProgram(programShader); this->CheckLinkage(static_cast(programShader)); this->ScaleBiasProgramShader=static_cast(programShader); this->UFrameBufferTexture= static_cast(vtkgl::GetUniformLocation(programShader, "frameBufferTexture")); this->UScale=static_cast(vtkgl::GetUniformLocation(programShader, "scale")); this->UBias=static_cast(vtkgl::GetUniformLocation(programShader, "bias")); } } //----------------------------------------------------------------------------- // Render the offscreen buffer to the screen. // \pre ren_exists: ren!=0 //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::RenderTextureToScreen(vtkRenderer *ren) { assert("pre: ren_exists" && ren!=0); if ( this->GeneratingCanonicalView ) { // We just need to copy of the data, not render it glBindTexture(GL_TEXTURE_2D, this->TextureObjects[ vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glPixelStorei( GL_PACK_ALIGNMENT, 1 ); unsigned char *outPtr = static_cast(this->CanonicalViewImageData->GetScalarPointer()); glGetTexImage( GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, outPtr ); return; } int lowerLeft[2]; int usize, vsize; ren->GetTiledSizeAndOrigin(&usize,&vsize,lowerLeft,lowerLeft+1); glViewport(lowerLeft[0],lowerLeft[1], usize, vsize); glEnable( GL_SCISSOR_TEST ); glScissor(lowerLeft[0],lowerLeft[1], usize, vsize); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, usize, 0.0, vsize, -1.0, 1.0 ); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_BLEND); glBlendFunc( GL_ONE,GL_ONE_MINUS_SRC_ALPHA); // As we use replace mode, we don't need to set the color value. glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glDisable(GL_DEPTH_TEST); double xOffset = 1.0 / usize; double yOffset = 1.0 / vsize; glDepthMask(GL_FALSE); double scale=1.0/this->FinalColorWindow; double bias=0.5-this->FinalColorLevel/this->FinalColorWindow; if(scale!=1.0 || bias!=0.0) { this->BuildScaleBiasProgram(); vtkgl::UseProgram(this->ScaleBiasProgramShader); if(this->UFrameBufferTexture!=-1) { vtkgl::Uniform1i(this->UFrameBufferTexture,0); } else { vtkErrorMacro(<<"uFrameBufferTexture is not a uniform variable."); } if(this->UScale!=-1) { vtkgl::Uniform1f(this->UScale,static_cast(scale)); } else { vtkErrorMacro(<<"uScale is not a uniform variable."); } if(this->UBias!=-1) { vtkgl::Uniform1f(this->UBias,static_cast(bias)); } else { vtkErrorMacro(<<"uBias is not a uniform variable."); } } else { glEnable(GL_TEXTURE_2D); // fixed pipeline } glBegin(GL_QUADS); glTexCoord2f(static_cast(xOffset),static_cast(yOffset)); glVertex2f(0.0,0.0); glTexCoord2f(static_cast(this->ReductionFactor-xOffset), static_cast(yOffset)); glVertex2f(static_cast(usize),0.0); glTexCoord2f(static_cast(this->ReductionFactor-xOffset), static_cast(this->ReductionFactor-yOffset)); glVertex2f(static_cast(usize),static_cast(vsize)); glTexCoord2f(static_cast(xOffset), static_cast(this->ReductionFactor-yOffset)); glVertex2f(0.0,static_cast(vsize)); glEnd(); // Restore the default mode. Used in overlay. glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); if(scale!=1.0 || bias!=0.0) { vtkgl::UseProgram(0); } else { glDisable(GL_TEXTURE_2D); } glDepthMask(GL_TRUE); glDisable(GL_BLEND); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } //----------------------------------------------------------------------------- // Update the reduction factor of the render viewport (this->ReductionFactor) // according to the time spent in seconds to render the previous frame // (this->TimeToDraw) and a time in seconds allocated to render the next // frame (allocatedTime). // \pre valid_current_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 // \pre positive_TimeToDraw: this->TimeToDraw>=0.0 // \pre positive_time: allocatedTime>0.0 // \post valid_new_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::ComputeReductionFactor( double allocatedTime) { assert("pre: valid_current_reduction_range" && this->ReductionFactor>0.0 && this->ReductionFactor<=1.0); assert("pre: positive_TimeToDraw" && this->TimeToDraw>=0.0); assert("pre: positive_time" && allocatedTime>0.0); if ( this->GeneratingCanonicalView ) { this->ReductionFactor = 1.0; return; } if ( !this->AutoAdjustSampleDistances ) { this->ReductionFactor = 1.0 / this->ImageSampleDistance; return; } if ( this->TimeToDraw ) { double oldFactor = this->ReductionFactor; double timeToDraw; if (allocatedTime < 1.0) { timeToDraw = this->SmallTimeToDraw; if ( timeToDraw == 0.0 ) { timeToDraw = this->BigTimeToDraw/3.0; } } else { timeToDraw = this->BigTimeToDraw; } if ( timeToDraw == 0.0 ) { timeToDraw = 10.0; } double fullTime = timeToDraw / this->ReductionFactor; double newFactor = allocatedTime / fullTime; if ( oldFactor == 1.0 || newFactor / oldFactor > 1.3 || newFactor / oldFactor < .95 ) { this->ReductionFactor = (newFactor+oldFactor)/2.0; this->ReductionFactor = (this->ReductionFactor > 5.0)?(1.00):(this->ReductionFactor); this->ReductionFactor = (this->ReductionFactor > 1.0)?(0.99):(this->ReductionFactor); this->ReductionFactor = (this->ReductionFactor < 0.1)?(0.10):(this->ReductionFactor); if ( 1.0/this->ReductionFactor > this->MaximumImageSampleDistance ) { this->ReductionFactor = 1.0 / this->MaximumImageSampleDistance; } if ( 1.0/this->ReductionFactor < this->MinimumImageSampleDistance ) { this->ReductionFactor = 1.0 / this->MinimumImageSampleDistance; } } } else { this->ReductionFactor = 1.0; } assert("post: valid_new_reduction_range" && this->ReductionFactor>0.0 && this->ReductionFactor<=1.0); } //----------------------------------------------------------------------------- // Rendering initialization including making the context current, loading // necessary extensions, allocating frame buffers, updating transfer function, // computing clipping regions, and building the fragment shader. // // Pre-conditions: // - ren != NULL // - vol != NULL // - ren->GetRenderWindow() != NULL // - 1 <= numberOfScalarComponents <= 4 // - numberOfLevels >= 1 //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::PreRender(vtkRenderer *ren, vtkVolume *vol, double datasetBounds[6], double scalarRange[2], int numberOfScalarComponents, unsigned int numberOfLevels) { // make sure our window is the current OpenGL context. ren->GetRenderWindow()->MakeCurrent(); // If we haven't already succeeded in loading the extensions, // try to load them if(!this->LoadExtensionsSucceeded) { this->LoadExtensions(ren->GetRenderWindow()); } // If we can't load the necessary extensions, provide // feedback on why it failed. if(!this->LoadExtensionsSucceeded) { vtkErrorMacro( "Rendering failed because the following OpenGL extensions " "are required but not supported: " << (this->UnsupportedRequiredExtensions->Stream.str()).c_str()); return; } // Create the OpenGL object that we need this->CreateOpenGLObjects(); // Compute the reduction factor that may be necessary to get // the interactive rendering rate that we want this->ComputeReductionFactor(vol->GetAllocatedRenderTime()); // Allocate the frame buffers if(!this->AllocateFrameBuffers(ren)) { vtkErrorMacro("Not enough GPU memory to create a framebuffer."); return; } // Save the scalar range - this is what we will use for the range // of the transfer functions this->TableRange[0]=scalarRange[0]; this->TableRange[1]=scalarRange[1]; if(this->RGBTable==0) { this->RGBTable=new vtkRGBTable; } if(this->MaskInput!=0) { if(this->Mask1RGBTable==0) { this->Mask1RGBTable=new vtkRGBTable; } if(this->Mask2RGBTable==0) { this->Mask2RGBTable=new vtkRGBTable; } } // Update the color transfer function this->UpdateColorTransferFunction(vol,numberOfScalarComponents); // Update the noise texture that will be used to jitter rays to // reduce alliasing artifacts this->UpdateNoiseTexture(); // We are going to change the blending mode and blending function - // so lets push here so we can pop later glPushAttrib(GL_COLOR_BUFFER_BIT); // If this is the canonical view - we don't want to intermix so we'll just // start by clearing the z buffer. if ( this->GeneratingCanonicalView ) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } // See if the volume transform is orientation-preserving vtkMatrix4x4 *m=vol->GetMatrix(); double det=vtkMath::Determinant3x3( m->GetElement(0,0),m->GetElement(0,1),m->GetElement(0,2), m->GetElement(1,0),m->GetElement(1,1),m->GetElement(1,2), m->GetElement(2,0),m->GetElement(2,1),m->GetElement(2,2)); this->PreserveOrientation=det>0; // If we have clipping planes, render the back faces of the clipped // bounding box of the whole dataset to set the zbuffer. if(this->ClippingPlanes && this->ClippingPlanes->GetNumberOfItems()!=0) { // push the model view matrix onto the stack, make sure we // adjust the mode first glMatrixMode(GL_MODELVIEW); glPushMatrix(); this->TempMatrix[0]->DeepCopy(vol->GetMatrix()); this->TempMatrix[0]->Transpose(); glMultMatrixd(this->TempMatrix[0]->Element[0]); this->ClipBoundingBox(ren,datasetBounds,vol); glEnable (GL_CULL_FACE); glCullFace (GL_FRONT); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); this->RenderClippedBoundingBox(0,0,1,ren->GetRenderWindow()); glDisable (GL_CULL_FACE); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); //glMatrixMode(GL_MODELVIEW); glPopMatrix(); } // Check if everything is OK this->CheckFrameBufferStatus(); // Intermixed geometry: Grab the depth buffer into a texture int size[2]; int lowerLeft[2]; ren->GetTiledSizeAndOrigin(size,size+1,lowerLeft,lowerLeft+1); vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); glBindTexture(GL_TEXTURE_2D, static_cast( this->TextureObjects[ vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectDepthMap])); glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,lowerLeft[0],lowerLeft[1],size[0], size[1]); vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); int parallelProjection=ren->GetActiveCamera()->GetParallelProjection(); // initialize variables to prevent compiler warnings. int rayCastMethod=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP; int shadeMethod=vtkMitkOpenGLGPUVolumeRayCastMapperShadeNotUsed; int componentMethod=vtkMitkOpenGLGPUVolumeRayCastMapperComponentNotUsed; switch(this->BlendMode) { case vtkVolumeMapper::COMPOSITE_BLEND: switch(numberOfScalarComponents) { case 1: componentMethod=vtkMitkOpenGLGPUVolumeRayCastMapperComponentOne; break; case 4: componentMethod=vtkMitkOpenGLGPUVolumeRayCastMapperComponentFour; break; default: assert("check: impossible case" && false); break; } if(this->MaskInput!=0) { rayCastMethod= vtkMitkOpenGLGPUVolumeRayCastMapperMethodCompositeMask; } else { //cout<<"program is composite+shade"<GetProperty()->GetShade() ) { shadeMethod=vtkMitkOpenGLGPUVolumeRayCastMapperShadeYes; assert("check: only_1_component_todo" && numberOfScalarComponents==1); } else { shadeMethod=vtkMitkOpenGLGPUVolumeRayCastMapperShadeNo; //cout<<"program is composite"<ComputeNumberOfCroppingRegions(); // TODO AMR vs single block if(this->AMRMode) { NumberOfCroppingRegions=2; // >1, means use do compositing between blocks } this->BuildProgram(parallelProjection,rayCastMethod,shadeMethod, componentMethod); this->CheckLinkage(this->ProgramShader); vtkgl::UseProgram(this->ProgramShader); // for active texture 0, dataset if(numberOfScalarComponents==1) { // colortable vtkgl::ActiveTexture(vtkgl::TEXTURE1); this->RGBTable->Bind(); if(this->MaskInput!=0) { vtkgl::ActiveTexture(vtkgl::TEXTURE8); this->Mask1RGBTable->Bind(); vtkgl::ActiveTexture(vtkgl::TEXTURE9); this->Mask2RGBTable->Bind(); } } GLint uDataSetTexture; uDataSetTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"dataSetTexture"); if(uDataSetTexture!=-1) { vtkgl::Uniform1i(uDataSetTexture,0); } else { vtkErrorMacro(<<"dataSetTexture is not a uniform variable."); } if ( this->MaskInput) { // Make the mask texture available on texture unit 7 GLint uMaskTexture; uMaskTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"maskTexture"); if(uMaskTexture!=-1) { vtkgl::Uniform1i(uMaskTexture,7); } else { vtkErrorMacro(<<"maskTexture is not a uniform variable."); } } if(numberOfScalarComponents==1) { GLint uColorTexture; uColorTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"colorTexture"); if(uColorTexture!=-1) { vtkgl::Uniform1i(uColorTexture,1); } else { vtkErrorMacro(<<"colorTexture is not a uniform variable."); } if(this->MaskInput!=0) { GLint uMask1ColorTexture; uMask1ColorTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"mask1ColorTexture"); if(uMask1ColorTexture!=-1) { vtkgl::Uniform1i(uMask1ColorTexture,8); } else { vtkErrorMacro(<<"mask1ColorTexture is not a uniform variable."); } GLint uMask2ColorTexture; uMask2ColorTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"mask2ColorTexture"); if(uMask2ColorTexture!=-1) { vtkgl::Uniform1i(uMask2ColorTexture,9); } else { vtkErrorMacro(<<"mask2ColorTexture is not a uniform variable."); } GLint uMaskBlendFactor; uMaskBlendFactor=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"maskBlendFactor"); if(uMaskBlendFactor!=-1) { vtkgl::Uniform1f(uMaskBlendFactor,this->MaskBlendFactor); } else { vtkErrorMacro(<<"maskBlendFactor is not a uniform variable."); } } } GLint uOpacityTexture; uOpacityTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"opacityTexture"); if(uOpacityTexture!=-1) { vtkgl::Uniform1i(uOpacityTexture,2); } else { vtkErrorMacro(<<"opacityTexture is not a uniform variable."); } // depthtexture vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); glBindTexture(GL_TEXTURE_2D,static_cast(this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectDepthMap])); GLint uDepthTexture; uDepthTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"depthTexture"); if(uDepthTexture!=-1) { vtkgl::Uniform1i(uDepthTexture,3); } else { vtkErrorMacro(<<"depthTexture is not a uniform variable."); } // noise texture vtkgl::ActiveTexture( vtkgl::TEXTURE6 ); glBindTexture(GL_TEXTURE_2D,static_cast(this->NoiseTextureId)); GLint uNoiseTexture; uNoiseTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"noiseTexture"); if(uNoiseTexture!=-1) { vtkgl::Uniform1i(uNoiseTexture,6); } else { vtkErrorMacro(<<"noiseTexture is not a uniform variable."); } this->CheckFrameBufferStatus(); if(this->NumberOfCroppingRegions>1) { // framebuffer texture if(rayCastMethod!=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP && rayCastMethod!=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIP) { vtkgl::ActiveTexture( vtkgl::TEXTURE4 ); glBindTexture(GL_TEXTURE_2D,static_cast(this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront])); GLint uFrameBufferTexture; uFrameBufferTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"frameBufferTexture"); this->PrintError("framebuffertexture 1"); if(uFrameBufferTexture!=-1) { vtkgl::Uniform1i(uFrameBufferTexture,4); } else { vtkErrorMacro(<<"frameBufferTexture is not a uniform variable."); } this->PrintError("framebuffertexture 2"); } this->CheckFrameBufferStatus(); // max scalar value framebuffer texture if(this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) { vtkgl::ActiveTexture( vtkgl::TEXTURE5 ); glBindTexture(GL_TEXTURE_2D,static_cast(this->MaxValueFrameBuffer2)); GLint uScalarBufferTexture; uScalarBufferTexture=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"scalarBufferTexture"); this->PrintError("scalarbuffertexture 1"); if(uScalarBufferTexture!=-1) { vtkgl::Uniform1i(uScalarBufferTexture,5); } else { vtkErrorMacro(<<"scalarBufferTexture is not a uniform variable."); } this->PrintError("scalarbuffertexture 2"); } } this->CheckFrameBufferStatus(); GLint uWindowLowerLeftCorner; uWindowLowerLeftCorner=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"windowLowerLeftCorner"); if(uWindowLowerLeftCorner!=-1) { vtkgl::Uniform2f(uWindowLowerLeftCorner,static_cast(lowerLeft[0]), static_cast(lowerLeft[1])); } else { vtkErrorMacro(<<"windowLowerLeftCorner is not a uniform variable."); } GLint uInvOriginalWindowSize; uInvOriginalWindowSize=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"invOriginalWindowSize"); if(uInvOriginalWindowSize!=-1) { vtkgl::Uniform2f(uInvOriginalWindowSize, static_cast(1.0/size[0]), static_cast(1.0/size[1])); } else { // yes it is not error. It is only actually used when there is some // complex cropping (this->NumberOfCroppingRegions>1). Some GLSL compilers // may remove the uniform variable for optimization when it is not used. vtkDebugMacro( <<"invOriginalWindowSize is not an active uniform variable."); } size[0] = static_cast(size[0]*this->ReductionFactor); size[1] = static_cast(size[1]*this->ReductionFactor); GLint uInvWindowSize; uInvWindowSize=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"invWindowSize"); if(uInvWindowSize!=-1) { vtkgl::Uniform2f(uInvWindowSize,static_cast(1.0/size[0]), static_cast(1.0/size[1])); } else { vtkErrorMacro(<<"invWindowSize is not a uniform variable."); } this->PrintError("after uniforms for textures"); this->CheckFrameBufferStatus(); GLint savedFrameBuffer; glGetIntegerv(vtkgl::FRAMEBUFFER_BINDING_EXT,&savedFrameBuffer); this->SavedFrameBuffer=static_cast(savedFrameBuffer); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(this->FrameBufferObject)); this->BindFramebuffer(); GLenum buffer[4]; buffer[0] = vtkgl::COLOR_ATTACHMENT0_EXT; if(this->NumberOfCroppingRegions>1 && this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND) { // max scalar frame buffer buffer[1] = vtkgl::COLOR_ATTACHMENT1_EXT; } else { buffer[1] = GL_NONE; } vtkgl::DrawBuffers(2,buffer); this->CheckFrameBufferStatus(); // Use by the composite+shade program double shininess=vol->GetProperty()->GetSpecularPower(); if(shininess>128.0) { shininess=128.0; // upper limit for the OpenGL shininess. } glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,static_cast(shininess)); glDisable(GL_COLOR_MATERIAL); // other mapper may have enable that. GLfloat values[4]; values[3]=1.0; values[0]=0.0; values[1]=values[0]; values[2]=values[0]; glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,values); values[0]=static_cast(vol->GetProperty()->GetAmbient()); values[1]=values[0]; values[2]=values[0]; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,values); values[0]=static_cast(vol->GetProperty()->GetDiffuse()); values[1]=values[0]; values[2]=values[0]; glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,values); values[0]=static_cast(vol->GetProperty()->GetSpecular()); values[1]=values[0]; values[2]=values[0]; glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,values); // cout << "pingpong=" << this->PingPongFlag << endl; // To initialize the second color buffer vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront], 0); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D, this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+1], 0); buffer[0] = vtkgl::COLOR_ATTACHMENT0_EXT; buffer[1] = vtkgl::COLOR_ATTACHMENT1_EXT; vtkgl::DrawBuffers(2,buffer); // cout << "check before setup" << endl; this->CheckFrameBufferStatus(); this->SetupRender(ren,vol); // restore in case of composite with no cropping or streaming. buffer[0] = vtkgl::COLOR_ATTACHMENT0_EXT; buffer[1] = GL_NONE; vtkgl::DrawBuffers(2,buffer); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D,0,0); // cout << "check after color init" << endl; this->CheckFrameBufferStatus(); if(this->NumberOfCroppingRegions>1 && (this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MAXIMUM_INTENSITY_BLEND)) { // cout << "this->MaxValueFrameBuffer="<< this->MaxValueFrameBuffer <MaxValueFrameBuffer2="<< this->MaxValueFrameBuffer2 <MaxValueFrameBuffer,0); vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D, this->MaxValueFrameBuffer2,0); buffer[0] = vtkgl::COLOR_ATTACHMENT0_EXT; buffer[1] = vtkgl::COLOR_ATTACHMENT1_EXT; vtkgl::DrawBuffers(2,buffer); if(this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) { glClearColor(1.0, 0.0, 0.0, 0.0); } else { glClearColor(0.0, 0.0, 0.0, 0.0); // for MAXIMUM_INTENSITY_BLEND } // cout << "check before clear on max" << endl; this->CheckFrameBufferStatus(); glClear(GL_COLOR_BUFFER_BIT); } if(this->NumberOfCroppingRegions>1) { // color buffer target in the color attachement 0 vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront], 0); // color buffer input is on texture unit 4. vtkgl::ActiveTexture(vtkgl::TEXTURE4); glBindTexture(GL_TEXTURE_2D,this->TextureObjects[vtkMitkOpenGLGPUVolumeRayCastMapperTextureObjectFrameBufferLeftFront+1]); if(this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) { // max buffer target in the color attachment 1 vtkgl::FramebufferTexture2DEXT(vtkgl::FRAMEBUFFER_EXT, vtkgl::COLOR_ATTACHMENT0_EXT+1, GL_TEXTURE_2D, this->MaxValueFrameBuffer,0); // max buffer input is on texture unit 5. vtkgl::ActiveTexture(vtkgl::TEXTURE5); glBindTexture(GL_TEXTURE_2D,this->MaxValueFrameBuffer2); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } this->CheckFrameBufferStatus(); if(this->OpacityTables!=0 && this->OpacityTables->Vector.size()!=numberOfLevels) { delete this->OpacityTables; this->OpacityTables=0; } if(this->OpacityTables==0) { this->OpacityTables=new vtkOpacityTables(numberOfLevels); } // debug code // DO NOT REMOVE the following commented line // this->ValidateProgram(); glCullFace (GL_BACK); // otherwise, we are rendering back face to initialize the zbuffer. if(!this->GeneratingCanonicalView && this->ReportProgress) { // initialize the time to avoid a progress event at the beginning. this->LastProgressEventTime=vtkTimerLog::GetUniversalTime(); } this->PrintError("PreRender end"); } //----------------------------------------------------------------------------- // Compute how each axis of a cell is projected on the viewport in pixel. // This requires to have information about the camera and about the volume. // It set the value of IgnoreSampleDistancePerPixel to true in case of // degenerated case (axes aligned with the view). //----------------------------------------------------------------------------- double vtkMitkOpenGLGPUVolumeRayCastMapper::ComputeMinimalSampleDistancePerPixel( vtkRenderer *renderer, vtkVolume *volume) { // For each of the 3 directions of a cell, compute the step in z // (world coordinate, not eye/camera coordinate) // to go to the next pixel in x. // Same for the next pixel in y. // Keep the minimum of both zstep // Then keep the minimum for the 3 directions. // in case of either the numerator or the denominator of each ratio is 0. this->IgnoreSampleDistancePerPixel=true; double result=0.0; vtkMatrix4x4 *worldToDataset=volume->GetMatrix(); vtkCamera *camera=renderer->GetActiveCamera(); vtkMatrix4x4 *eyeToWorld=camera->GetViewTransformMatrix(); vtkMatrix4x4 *eyeToDataset=vtkMatrix4x4::New(); vtkMatrix4x4::Multiply4x4(eyeToWorld,worldToDataset,eyeToDataset); int usize; int vsize; renderer->GetTiledSize(&usize,&vsize); vtkMatrix4x4 *viewportToEye=camera->GetProjectionTransformMatrix( usize/static_cast(vsize),0.0,1.0); double volBounds[6]; this->GetInput()->GetBounds(volBounds); int dims[3]; this->GetInput()->GetDimensions(dims); double v0[4]; v0[0]=volBounds[0]; v0[1]=volBounds[2]; v0[2]=volBounds[4]; v0[3]=1.0; double w0[4]; eyeToDataset->MultiplyPoint(v0,w0); double z0; if(w0[3]!=0.0) { z0=w0[2]/w0[3]; } else { z0=0.0; vtkGenericWarningMacro( "eyeToWorld transformation has some projective component." ); } double p0[4]; viewportToEye->MultiplyPoint(w0,p0); p0[0]/=p0[3]; p0[1]/=p0[3]; p0[2]/=p0[3]; bool inFrustum=p0[0]>=-1.0 && p0[0]<=1.0 && p0[1]>=-1.0 && p0[1]<=1.0 && p0[2]>=-1.0 && p0[2]<=1.0; if(inFrustum) { int dim=0; while(dim<3) { double v1[4]; int coord=0; while(coord<3) { if(coord==dim) { v1[coord]=volBounds[2*coord+1]; } else { v1[coord]=volBounds[2*coord]; // same as v0[coord]; } ++coord; } v1[3]=1.0; double w1[4]; eyeToDataset->MultiplyPoint(v1,w1); double z1; if(w1[3]!=0.0) { z1=w1[2]/w1[3]; } else { z1=0.0; vtkGenericWarningMacro( "eyeToWorld transformation has some projective component." ); } double p1[4]; viewportToEye->MultiplyPoint(w1,p1); p1[0]/=p1[3]; p1[1]/=p1[3]; p1[2]/=p1[3]; inFrustum=p1[0]>=-1.0 && p1[0]<=1.0 && p1[1]>=-1.0 && p1[1]<=1.0 && p1[2]>=-1.0 && p1[2]<=1.0; if(inFrustum) { double dx=fabs(p1[0]-p0[0]); double dy=fabs(p1[1]-p0[1]); double dz=fabs(z1-z0); dz=dz/(dims[dim]-1); dx=dx/(dims[dim]-1)*usize; dy=dy/(dims[dim]-1)*vsize; if(dz!=0.0) { if(dx!=0.0) { double d=dz/dx; if(!this->IgnoreSampleDistancePerPixel) { if(result>d) { result=d; } } else { this->IgnoreSampleDistancePerPixel=false; result=d; } } if(dy!=0.0) { double d=dz/dy; if(!this->IgnoreSampleDistancePerPixel) { if(result>d) { result=d; } } else { this->IgnoreSampleDistancePerPixel=false; result=d; } } } } ++dim; } } eyeToDataset->Delete(); if(this->IgnoreSampleDistancePerPixel) { // cout<<"ignore SampleDistancePerPixel"<ValidateProgram(); this->PrintError("before render"); if(!this->Cropping) { this->RenderWholeVolume(ren,vol); } else { this->ClipCroppingRegionPlanes(); this->RenderRegions(ren,vol); } this->PrintError("after render"); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::PostRender( vtkRenderer *ren, int numberOfScalarComponents) { this->PrintError("PostRender1"); if(this->NumberOfCroppingRegions>1) { if(this->BlendMode==vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND || this->BlendMode==vtkMitkGPUVolumeRayCastMapper::MINIMUM_INTENSITY_BLEND) { vtkgl::ActiveTexture( vtkgl::TEXTURE5 ); glBindTexture(GL_TEXTURE_2D,0); } if(this->LastRayCastMethod!=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP && this->LastRayCastMethod!=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIP) { vtkgl::ActiveTexture( vtkgl::TEXTURE4 ); glBindTexture(GL_TEXTURE_2D,0); } } // noisetexture vtkgl::ActiveTexture(vtkgl::TEXTURE6); glBindTexture(GL_TEXTURE_2D,0); // depthtexture vtkgl::ActiveTexture(vtkgl::TEXTURE3); glBindTexture(GL_TEXTURE_2D,0); // opacity vtkgl::ActiveTexture(vtkgl::TEXTURE2); glBindTexture(GL_TEXTURE_1D,0); if(numberOfScalarComponents==1) { vtkgl::ActiveTexture(vtkgl::TEXTURE1); glBindTexture(GL_TEXTURE_1D,0); } // mask, if any if(this->MaskInput!=0) { vtkgl::ActiveTexture(vtkgl::TEXTURE7); glBindTexture(vtkgl::TEXTURE_3D_EXT,0); } // back to active texture 0. vtkgl::ActiveTexture(vtkgl::TEXTURE0); glBindTexture(vtkgl::TEXTURE_3D_EXT,0); vtkgl::UseProgram(0); this->PrintError("after UseProgram(0)"); this->CleanupRender(); this->PrintError("after CleanupRender"); vtkgl::BindFramebufferEXT(vtkgl::FRAMEBUFFER_EXT, static_cast(this->SavedFrameBuffer)); this->SavedFrameBuffer=0; // Undo the viewport change we made to reduce resolution int size[2]; int lowerLeft[2]; ren->GetTiledSizeAndOrigin(size,size+1,lowerLeft,lowerLeft+1); glViewport(lowerLeft[0],lowerLeft[1], size[0], size[1]); glEnable( GL_SCISSOR_TEST ); glScissor(lowerLeft[0],lowerLeft[1], size[0], size[1]); // Render the texture to the screen - this copies the offscreen buffer // onto the screen as a texture mapped polygon this->RenderTextureToScreen(ren); this->PrintError("after RenderTextureToScreen"); glEnable(GL_DEPTH_TEST); glPopAttrib(); // restore the blending mode and function glFinish(); this->PrintError("PostRender2"); } //----------------------------------------------------------------------------- // The main render method called from the superclass //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::GPURender(vtkRenderer *ren, vtkVolume *vol) { // We've already checked that we have input vtkImageData *input = this->GetTransformedInput(); // Get the bounds of this data double bounds[6]; this->GetBounds(bounds); // Get the scalar range. First we have to get the scalars. double range[2]; vtkDataArray *scalars=this->GetScalars(input,this->ScalarMode, this->ArrayAccessMode, this->ArrayId,this->ArrayName, this->CellFlag); // How many components are there? int numberOfScalarComponents=scalars->GetNumberOfComponents(); // If it is just one, then get the range from the scalars if(numberOfScalarComponents==1) { // Warning: here, we ignore the blank cells. scalars->GetRange(range); } // If it is 3, then use the 4th component's range since that is // the component that will be passed through the scalar opacity // transfer function to look up opacity else { // Note that we've already checked data type and we know this is // unsigned char scalars->GetRange(range,3); } // The rendering work has been broken into 3 stages to support AMR // volume rendering in blocks. Here we are simply rendering the // whole volume as one block. Note that if the volume is too big // to fix into texture memory, it will be streamed through in the // RenderBlock method. this->PreRender(ren,vol,bounds,range,numberOfScalarComponents,1); if(!this->OpacityTables) this->PreRender(ren,vol,bounds,range,numberOfScalarComponents,1); if(this->LoadExtensionsSucceeded) { this->RenderBlock(ren,vol,0); this->PostRender(ren,numberOfScalarComponents); } // Let's just make sure no OpenGL errors occurred during this render this->PrintError("End GPU Render"); // If this isn't a canonical view render, then update the progress to // 1 because we are done. if (!this->GeneratingCanonicalView ) { double progress=1.0; this->InvokeEvent(vtkCommand::VolumeMapperRenderProgressEvent,&progress); ren->GetRenderWindow()->MakeCurrent(); } } //----------------------------------------------------------------------------- // Render a the whole volume. // \pre this->ProgramShader!=0 and is linked. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::RenderWholeVolume(vtkRenderer *ren, vtkVolume *vol) { double volBounds[6]; this->GetTransformedInput()->GetBounds(volBounds); this->RenderSubVolume(ren,volBounds,vol); } //----------------------------------------------------------------------------- // Sort regions from front to back. //----------------------------------------------------------------------------- class vtkRegionDistance2 { public: size_t Id; // 0<=Id<27 // square distance between camera center to region center: >=0 double Distance2; }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- extern "C" int vtkRegionComparisonFunction(const void *x, const void *y) { double dx=static_cast(x)->Distance2; double dy=static_cast(y)->Distance2; int result; if(dxdy) { result=1; } else { result=0; } } return result; } //----------------------------------------------------------------------------- // Render a subvolume. // \pre this->ProgramShader!=0 and is linked. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::RenderRegions(vtkRenderer *ren, vtkVolume *vol) { double bounds[27][6]; double distance2[27]; double camPos[4]; ren->GetActiveCamera()->GetPosition(camPos); double volBounds[6]; this->GetInput()->GetBounds(volBounds); // Pass camera through inverse volume matrix // so that we are in the same coordinate system vol->GetMatrix( this->InvVolumeMatrix ); camPos[3] = 1.0; this->InvVolumeMatrix->Invert(); this->InvVolumeMatrix->MultiplyPoint( camPos, camPos ); if ( camPos[3] ) { camPos[0] /= camPos[3]; camPos[1] /= camPos[3]; camPos[2] /= camPos[3]; } // These are the region limits for x (first four), y (next four) and // z (last four). The first region limit is the lower bound for // that axis, the next two are the region planes along that axis, and // the final one in the upper bound for that axis. double limit[12]; size_t i; for ( i = 0; i < 3; i++ ) { limit[i*4 ] = volBounds[i*2]; limit[i*4+1] = this->ClippedCroppingRegionPlanes[i*2]; limit[i*4+2] = this->ClippedCroppingRegionPlanes[i*2+1]; limit[i*4+3] = volBounds[i*2+1]; } // For each of the 27 possible regions, find out if it is enabled, // and if so, compute the bounds and the distance from the camera // to the center of the region. size_t numRegions = 0; size_t region; for ( region = 0; region < 27; region++ ) { int regionFlag = 1<CroppingRegionFlags & regionFlag ) { // what is the coordinate in the 3x3x3 grid size_t loc[3]; loc[0] = region%3; loc[1] = (region/3)%3; loc[2] = (region/9)%3; // make sure the cropping region is not empty NEW // otherwise, we skip the region. if((limit[loc[0]]!=limit[loc[0]+1]) && (limit[loc[1]+4]!=limit[loc[1]+5]) && (limit[loc[2]+8]!=limit[loc[2]+9])) { // compute the bounds and center double center[3]; for ( i = 0; i < 3; i++ ) { bounds[numRegions][i*2 ] = limit[4*i+loc[i]]; bounds[numRegions][i*2+1] = limit[4*i+loc[i]+1]; center[i]=(bounds[numRegions][i*2]+bounds[numRegions][i*2+1])*0.5; } // compute the distance squared to the center distance2[numRegions] = (camPos[0]-center[0])*(camPos[0]-center[0]) + (camPos[1]-center[1])*(camPos[1]-center[1]) + (camPos[2]-center[2])*(camPos[2]-center[2]); // we've added one region numRegions++; } } } vtkRegionDistance2 regions[27]; i=0; while(iNumberOfCroppingRegions>=0); } //----------------------------------------------------------------------------- // slabsDataSet are position of the slabs in dataset coordinates. // slabsPoints are position of the slabs in points coordinates. // For instance, slabsDataSet[0] is the position of the plane bounding the slab // on the left of x axis of the dataset. slabsPoints[0]=0.3 means that // this plane lies between point 0 and point 1 along the x-axis. // There is no clamping/clipping according to the dataset bounds so, // slabsPoints can be negative or excess the number of points along the // corresponding axis. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::SlabsFromDatasetToIndex( double slabsDataSet[6], double slabsPoints[6]) { double *spacing=this->GetInput()->GetSpacing(); double origin[3]; // take spacing sign into account double *bds = this->GetInput()->GetBounds(); origin[0] = bds[0]; origin[1] = bds[2]; origin[2] = bds[4]; int i=0; while(i<6) { slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2]; ++i; } } //----------------------------------------------------------------------------- // slabsDataSet are position of the slabs in dataset coordinates. // slabsPoints are position of the slabs in points coordinates. // For instance, slabsDataSet[0] is the position of the plane bounding the slab // on the left of x axis of the dataset. slabsPoints[0]=0.3 means that // this plane lies between point 0 and point 1 along the x-axis. // There is no clamping/clipping according to the dataset bounds so, // slabsPoints can be negative or excess the number of points along the // corresponding axis. //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::SlabsFromIndexToDataset( double slabsPoints[6], double slabsDataSet[6]) { double *spacing=this->GetInput()->GetSpacing(); double origin[3]; // take spacing sign into account double *bds = this->GetInput()->GetBounds(); origin[0] = bds[0]; origin[1] = bds[2]; origin[2] = bds[4]; int i=0; while(i<6) { slabsDataSet[i]=slabsPoints[i]*spacing[i/2]+origin[i/2]; ++i; } } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class vtkStreamBlock { public: double Bounds[6]; double Extent[6]; }; //----------------------------------------------------------------------------- // Render a subvolume. bounds are in world coordinates. // \pre this->ProgramShader!=0 and is linked. //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::RenderSubVolume(vtkRenderer *ren, double bounds[6], vtkVolume *volume) { // Time to load scalar field size_t i; int wholeTextureExtent[6]; this->GetTransformedInput()->GetExtent(wholeTextureExtent); if(this->CellFlag) { i=1; while(i<6) { wholeTextureExtent[i]--; i+=2; } } // 1. Found out the extent of the subvolume double realExtent[6]; int subvolumeTextureExtent[6]; this->SlabsFromDatasetToIndex(bounds,realExtent); if(this->CellFlag) // 3D texture are celldata { // texture extents are expressed in cells in this case i=0; while(i<6) { subvolumeTextureExtent[i]=vtkMath::Floor(realExtent[i]-0.5); ++i; subvolumeTextureExtent[i]=vtkMath::Floor(realExtent[i]-0.5)+1; ++i; } } else { // texture extents are expressed in points in this case i=0; while(i<6) { subvolumeTextureExtent[i]=vtkMath::Floor(realExtent[i]); ++i; subvolumeTextureExtent[i]=vtkMath::Floor(realExtent[i])+1; // used to not have +1 ++i; } } i=0; while(i<6) { assert("check: wholeTextureExtent" && wholeTextureExtent[i]==0); if(subvolumeTextureExtent[i]wholeTextureExtent[i]) { subvolumeTextureExtent[i]=wholeTextureExtent[i]; } ++i; } assert("check: subvolume_inside_wholevolume" && subvolumeTextureExtent[0]>=wholeTextureExtent[0] && subvolumeTextureExtent[1]<=wholeTextureExtent[1] && subvolumeTextureExtent[2]>=wholeTextureExtent[2] && subvolumeTextureExtent[3]<=wholeTextureExtent[3] && subvolumeTextureExtent[4]>=wholeTextureExtent[4] && subvolumeTextureExtent[5]<=wholeTextureExtent[5]); // 2. Is this subvolume already on the GPU? // ie are the extent of the subvolume inside the loaded extent? // Find the texture (and mask). vtkstd::map::iterator it= this->ScalarsTextures->Map.find(this->GetTransformedInput()); vtkKWScalarField *texture; if(it==this->ScalarsTextures->Map.end()) { texture=0; } else { texture=(*it).second; } vtkKWMask *mask=0; if(this->MaskInput!=0) { vtkstd::map::iterator it2= this->MaskTextures->Map.find(this->MaskInput); if(it2==this->MaskTextures->Map.end()) { mask=0; } else { mask=(*it2).second; } } int loaded = texture!=0 && texture->IsLoaded() && this->GetTransformedInput()->GetMTime()<=texture->GetBuildTime() && (this->GetMaskInput() ? this->GetMaskInput()->GetMTime() <= texture->GetBuildTime() : true) && texture->GetLoadedCellFlag()==this->CellFlag; vtkIdType *loadedExtent; if(loaded) { loadedExtent=texture->GetLoadedExtent(); i=0; while(loaded && i<6) { loaded=loaded && loadedExtent[i]<=subvolumeTextureExtent[i]; ++i; loaded=loaded && loadedExtent[i]>=subvolumeTextureExtent[i]; ++i; } } if(loaded) { this->CurrentScalar=texture; vtkgl::ActiveTexture(vtkgl::TEXTURE0); this->CurrentScalar->Bind(); vtkgl::ActiveTexture(vtkgl::TEXTURE7); this->CurrentMask=mask; if(this->CurrentMask!=0) { this->CurrentMask->Bind(); } } if(!loaded) { // 3. Not loaded: try to load the whole dataset if(!this->LoadScalarField(this->GetTransformedInput(),this->MaskInput,wholeTextureExtent,volume)) { // 4. loading the whole dataset failed: try to load the subvolume if(!this->LoadScalarField(this->GetTransformedInput(),this->MaskInput, subvolumeTextureExtent, volume)) { // 5. loading the subvolume failed: stream the subvolume // 5.1 do zslabs first, if too large then cut with x or y with the // largest dimension. order of zlabs depends on sign of spacing[2] int streamTextureExtent[6]; i=0; while(i<6) { streamTextureExtent[i]=subvolumeTextureExtent[i]; ++i; } unsigned int internalFormat; unsigned int format; unsigned int type; int componentSize; this->GetTextureFormat(this->GetInput(),&internalFormat,&format,&type, &componentSize); // Enough memory? int originalTextureSize[3]; int textureSize[3]; i=0; while(i<3) { textureSize[i]=subvolumeTextureExtent[2*i+1]-subvolumeTextureExtent[2*i]+1; originalTextureSize[i]=textureSize[i]; ++i; } // Make sure loading did not fail because of theorical limits GLint width; glGetIntegerv(vtkgl::MAX_3D_TEXTURE_SIZE,&width); int clippedXY=0; int clippedZ=0; if(textureSize[0]>width) { textureSize[0]=width; clippedXY=1; } if(textureSize[1]>width) { textureSize[1]=width; clippedXY=1; } if(textureSize[2]>width) { textureSize[2]=width; clippedZ=1; } int minSize; if(this->CellFlag) { minSize=1; } else { minSize=2; } if(clippedXY) { // We cannot expect to first divide as z-slabs because it is already // clipped in another dimension. From now, just divide in the largest // dimension. bool foundSize=false; while(!foundSize && textureSize[0]>=minSize && textureSize[1]>=minSize) { foundSize=this->TestLoadingScalar(internalFormat,format,type, textureSize,componentSize); if(!foundSize) { int maxDim=0; if(textureSize[1]>textureSize[0]) { maxDim=1; } if(textureSize[2]>textureSize[maxDim]) { maxDim=2; } textureSize[maxDim]>>=1; // /=2 } } } else { // we are in cropping mode, it will be slow anyway. the case we want // to optimize is stream the all scalar field. With that in mine, // it is better to first try to send z-slabs. If even a minimal // z-slab is too big, we have to divide by x or y dimensions. In // this case, it will be slow and we can choose to keep blocks as // square as possible by dividing by the largest dimension at each // iteration. if(!clippedZ) { // we start by subdividing only if we did not already clipped // the z dimension according to the theorical limits. textureSize[2]>>=1; // /=2 } bool foundSize=false; while(!foundSize && textureSize[2]>=minSize) { foundSize=this->TestLoadingScalar(internalFormat,format,type, textureSize,componentSize); if(!foundSize) { textureSize[2]>>=1; // /=2 } } if(!foundSize) { textureSize[2]=minSize; if(textureSize[0]>textureSize[1]) { textureSize[0]>>=1; // /=2 } else { textureSize[1]>>=1; // /=2 } while(!foundSize && textureSize[0]>=minSize && textureSize[1]>=minSize) { foundSize=this->TestLoadingScalar(internalFormat,format,type, textureSize,componentSize); if(!foundSize) { if(textureSize[0]>textureSize[1]) { textureSize[0]>>=1; // /=2 } else { textureSize[1]>>=1; // /=2 } } } } if(!foundSize) { vtkErrorMacro( <<"No memory left on the GPU even for a minimal block."); return 1; // abort } } // except for the last bound. // front to back ordering // Pass camera through inverse volume matrix // so that we are in the same coordinate system double camPos[4]; vtkCamera *cam = ren->GetActiveCamera(); cam->GetPosition(camPos); volume->GetMatrix( this->InvVolumeMatrix ); camPos[3] = 1.0; this->InvVolumeMatrix->Invert(); this->InvVolumeMatrix->MultiplyPoint( camPos, camPos ); if ( camPos[3] ) { camPos[0] /= camPos[3]; camPos[1] /= camPos[3]; camPos[2] /= camPos[3]; } // 5.2 iterate of each stream of the subvolume and render it: // point scalar: on the first block, the first point is not shared // blockExtent is always expressed in point, not in texture // extent. size_t remainder[3]; i=0; while(i<3) { remainder[i]=static_cast( (originalTextureSize[i]-textureSize[i])%(textureSize[i]-1)); if(remainder[i]>0) { remainder[i]=1; } ++i; } size_t counts[3]; counts[0]=static_cast((originalTextureSize[0]-textureSize[0]) /(textureSize[0]-1)); counts[0]+=remainder[0]+1; counts[1]=static_cast((originalTextureSize[1]-textureSize[1]) /(textureSize[1]-1)); counts[1]+=remainder[1]+1; counts[2]=static_cast((originalTextureSize[2]-textureSize[2]) /(textureSize[2]-1)); counts[2]+=remainder[2]+1; size_t count=counts[0]*counts[1]*counts[2]; double blockExtent[6]; vtkStreamBlock *blocks=new vtkStreamBlock[count]; vtkRegionDistance2 *sortedBlocks=new vtkRegionDistance2[count]; // iterate over z,y,x size_t blockId=0; size_t zIndex=0; blockExtent[4]=realExtent[4]; blockExtent[5]=vtkMath::Floor(blockExtent[4])+textureSize[2]; if(!this->CellFlag) { blockExtent[5]--; } if(blockExtent[5]>realExtent[5]) { blockExtent[5]=realExtent[5]; } while(zIndexCellFlag) { blockExtent[3]--; } if(blockExtent[3]>realExtent[3]) { blockExtent[3]=realExtent[3]; } size_t yIndex=0; while(yIndexCellFlag) { blockExtent[1]--; } if(blockExtent[1]>realExtent[1]) { blockExtent[1]=realExtent[1]; } size_t xIndex=0; while(xIndexSlabsFromIndexToDataset(blockExtent,blockBounds); // compute the bounds and center double center[3]; i=0; while(i<3) { center[i]=(blockBounds[i*2]+blockBounds[i*2+1])*0.5; ++i; } // compute the distance squared to the center double distance2=(camPos[0]-center[0])*(camPos[0]-center[0])+ (camPos[1]-center[1])*(camPos[1]-center[1]) + (camPos[2]-center[2])*(camPos[2]-center[2]); i=0; while(i<6) { blocks[blockId].Bounds[i]=blockBounds[i]; blocks[blockId].Extent[i]=blockExtent[i]; ++i; } sortedBlocks[blockId].Id=blockId; sortedBlocks[blockId].Distance2=distance2; ++blockId; blockExtent[0]=blockExtent[1]; blockExtent[1]=blockExtent[0]+textureSize[0]; if(!this->CellFlag) { blockExtent[1]--; } if(blockExtent[1]>realExtent[1]) { blockExtent[1]=realExtent[1]; } ++xIndex; } // while x blockExtent[2]=blockExtent[3]; blockExtent[3]=blockExtent[2]+textureSize[1]; if(!this->CellFlag) { blockExtent[3]--; } if(blockExtent[3]>realExtent[3]) { blockExtent[3]=realExtent[3]; } ++yIndex; } // while y blockExtent[4]=blockExtent[5]; blockExtent[5]=blockExtent[4]+textureSize[2]; if(!this->CellFlag) { blockExtent[5]--; } if(blockExtent[5]>realExtent[5]) { blockExtent[5]=realExtent[5]; } ++zIndex; } // while z assert("check: valid_number_of_blocks" && blockId==count); qsort(sortedBlocks,static_cast(count), sizeof(vtkRegionDistance2), vtkRegionComparisonFunction); // loop over all blocks we need to render i=0; int abort=0; while(!abort && i < count) // 1) //count) { size_t k=sortedBlocks[i].Id; int blockTextureExtent[6]; int j; if(this->CellFlag) // 3D texture are celldata { // texture extents are expressed in cells in this case j=0; while(j<6) { blockTextureExtent[j]=vtkMath::Floor(blocks[k].Extent[j]); ++j; } } else { // texture extents are expressed in points in this case j=0; while(j<6) { blockTextureExtent[j]=vtkMath::Floor(blocks[k].Extent[j]); ++j; blockTextureExtent[j]=vtkMath::Floor(blocks[k].Extent[j]); if(blockTextureExtent[j]LoadScalarField(this->GetInput(),this->MaskInput, blockTextureExtent, volume)) { cout<<"Loading the streamed block FAILED!!!!!"<CurrentScalar->GetLoadedExtent(); float lowBounds[3]; float highBounds[3]; if(!this->CurrentScalar->GetLoadedCellFlag()) // points { j=0; while(j<3) { double delta= static_cast(loadedExtent[j*2+1]-loadedExtent[j*2]); lowBounds[j]=static_cast((blocks[k].Extent[j*2]-static_cast(loadedExtent[j*2]))/delta); highBounds[j]=static_cast((blocks[k].Extent[j*2+1]-static_cast(loadedExtent[j*2]))/delta); ++j; } } else // cells { j=0; while(j<3) { double delta= static_cast(loadedExtent[j*2+1]-loadedExtent[j*2]); lowBounds[j]=static_cast((blocks[k].Extent[j*2]-0.5-static_cast(loadedExtent[j*2]))/delta); highBounds[j]=static_cast((blocks[k].Extent[j*2+1]-0.5-static_cast(loadedExtent[j*2]))/delta); ++j; } } // bounds have to be normalized. There are used in the shader // as bounds to a value used to sample a texture. assert("check: positive_low_bounds0" && lowBounds[0]>=0.0); assert("check: positive_low_bounds1" && lowBounds[1]>=0.0); assert("check: positive_low_bounds2" && lowBounds[2]>=0.0); assert("check: increasing_bounds0" && lowBounds[0]<=highBounds[0]); assert("check: increasing_bounds1" && lowBounds[1]<=highBounds[1]); assert("check: increasing_bounds2" && lowBounds[2]<=highBounds[2]); assert("check: high_bounds0_less_than1" && highBounds[0]<=1.0); assert("check: high_bounds1_less_than1" && highBounds[1]<=1.0); assert("check: high_bounds2_less_than1" && highBounds[2]<=1.0); GLint lb; lb=vtkgl::GetUniformLocation(static_cast(this->ProgramShader), "lowBounds"); this->PrintError("get uniform low bounds"); if(lb!=-1) { vtkgl::Uniform3f(lb, lowBounds[0],lowBounds[1],lowBounds[2]); this->PrintError("set uniform low bounds"); } else { vtkErrorMacro(<<" lowBounds is not a uniform variable."); } GLint hb; hb=vtkgl::GetUniformLocation(static_cast(this->ProgramShader), "highBounds"); this->PrintError("get uniform high bounds"); if(hb!=-1) { vtkgl::Uniform3f(hb, highBounds[0],highBounds[1],highBounds[2]); this->PrintError("set uniform high bounds"); } else { vtkErrorMacro(<<" highBounds is not a uniform variable."); } this->PrintError("uniform low/high bounds block"); // other sub-volume rendering code this->LoadProjectionParameters(ren,volume); this->ClipBoundingBox(ren,blocks[k].Bounds,volume); abort=this->RenderClippedBoundingBox(1,i,count,ren->GetRenderWindow()); if (!abort) { this->CopyFBOToTexture(); } this->PrintError("render clipped block 1"); ++i; } delete[] blocks; delete[] sortedBlocks; return abort; } } } loadedExtent=this->CurrentScalar->GetLoadedExtent(); // low bounds and high bounds are in texture coordinates. float lowBounds[3]; float highBounds[3]; if(!this->CurrentScalar->GetLoadedCellFlag()) // points { i=0; while(i<3) { double delta= static_cast(loadedExtent[i*2+1]-loadedExtent[i*2]+1); lowBounds[i]=static_cast((realExtent[i*2]+0.5-static_cast(loadedExtent[i*2]))/delta); highBounds[i]=static_cast((realExtent[i*2+1]+0.5-static_cast(loadedExtent[i*2]))/delta); ++i; } } else // cells { i=0; while(i<3) { double delta= static_cast(loadedExtent[i*2+1]-loadedExtent[i*2]+1); // this->LoadedExtent[i*2]==0, texcoord starts at 0, if realExtent==0 // otherwise, texcoord start at 1/2N // this->LoadedExtent[i*2]==wholeTextureExtent[i*2+1], texcoord stops at 1, if realExtent==wholeTextureExtent[i*2+1]+1 // otherwise it stop at 1-1/2N // N is the number of texels in the loadedtexture not the number of // texels in the whole texture. lowBounds[i]=static_cast((realExtent[i*2]-static_cast(loadedExtent[i*2]))/delta); highBounds[i]=static_cast((realExtent[i*2+1]-static_cast(loadedExtent[i*2]))/delta); ++i; } } assert("check: positive_low_bounds0" && lowBounds[0]>=0.0); assert("check: positive_low_bounds1" && lowBounds[1]>=0.0); assert("check: positive_low_bounds2" && lowBounds[2]>=0.0); assert("check: increasing_bounds0" && lowBounds[0]<=highBounds[0]); assert("check: increasing_bounds1" && lowBounds[1]<=highBounds[1]); assert("check: increasing_bounds2" && lowBounds[2]<=highBounds[2]); assert("check: high_bounds0_less_than1" && highBounds[0]<=1.0); assert("check: high_bounds1_less_than1" && highBounds[1]<=1.0); assert("check: high_bounds2_less_than1" && highBounds[2]<=1.0); GLint lb; lb=vtkgl::GetUniformLocation(static_cast(this->ProgramShader), "lowBounds"); this->PrintError("get uniform low bounds"); if(lb!=-1) { vtkgl::Uniform3f(lb, lowBounds[0],lowBounds[1],lowBounds[2]); this->PrintError("set uniform low bounds"); } else { vtkErrorMacro(<<" lowBounds is not a uniform variable."); } GLint hb; hb=vtkgl::GetUniformLocation(static_cast(this->ProgramShader), "highBounds"); this->PrintError("get uniform high bounds"); if(hb!=-1) { vtkgl::Uniform3f(hb, highBounds[0],highBounds[1],highBounds[2]); this->PrintError("set uniform high bounds"); } else { vtkErrorMacro(<<" highBounds is not a uniform variable."); } this->PrintError("uniform low/high bounds"); // other sub-volume rendering code this->LoadProjectionParameters(ren,volume); this->ClipBoundingBox(ren,bounds,volume); int abort=this->RenderClippedBoundingBox(1,0,1,ren->GetRenderWindow()); if (!abort) { this->CopyFBOToTexture(); } this->PrintError("render clipped 1"); return abort; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::LoadProjectionParameters( vtkRenderer *ren, vtkVolume *vol) { vtkMatrix4x4 *worldToDataset=vol->GetMatrix(); vtkMatrix4x4 *datasetToWorld=this->TempMatrix[0]; vtkMatrix4x4::Invert(worldToDataset,datasetToWorld); double *bounds=this->CurrentScalar->GetLoadedBounds(); double dx=bounds[1]-bounds[0]; double dy=bounds[3]-bounds[2]; double dz=bounds[5]-bounds[4]; // worldToTexture matrix is needed // Compute change-of-coordinate matrix from world space to texture space. vtkMatrix4x4 *worldToTexture=this->TempMatrix[2]; vtkMatrix4x4 *datasetToTexture=this->TempMatrix[1]; // Set the matrix datasetToTexture->Zero(); datasetToTexture->SetElement(0,0,dx); datasetToTexture->SetElement(1,1,dy); datasetToTexture->SetElement(2,2,dz); datasetToTexture->SetElement(3,3,1.0); datasetToTexture->SetElement(0,3,bounds[0]); datasetToTexture->SetElement(1,3,bounds[2]); datasetToTexture->SetElement(2,3,bounds[4]); // worldToTexture=worldToDataSet*dataSetToTexture vtkMatrix4x4::Multiply4x4(worldToDataset,datasetToTexture,worldToTexture); // NEW int parallelProjection=ren->GetActiveCamera()->GetParallelProjection(); // cout << "actualSampleDistance=" << this->ActualSampleDistance << endl; if(parallelProjection) { // Unit vector of the direction of projection in world space. double dirWorld[4]; double dir[4]; ren->GetActiveCamera()->GetDirectionOfProjection(dirWorld); dirWorld[3]=0.0; // direction in dataset space. datasetToWorld->MultiplyPoint(dirWorld,dir); // incremental vector: // direction in texture space times sample distance in world space. dir[0]=dir[0]*this->ActualSampleDistance/dx; dir[1]=dir[1]*this->ActualSampleDistance/dy; dir[2]=dir[2]*this->ActualSampleDistance/dz; GLint rayDir; rayDir=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"parallelRayDirection"); if(rayDir!=-1) { vtkgl::Uniform3f(rayDir,static_cast(dir[0]), static_cast(dir[1]), static_cast(dir[2])); } else { vtkErrorMacro(<<"parallelRayDirection is not a uniform variable."); } //cout<<"rayDir="<GetActiveCamera()->GetPosition(cameraPosWorld); cameraPosWorld[3]=1.0; // we use homogeneous coordinates. datasetToWorld->MultiplyPoint(cameraPosWorld,cameraPosDataset); // From homogeneous to cartesian coordinates. if(cameraPosDataset[3]!=1.0) { double ratio=1/cameraPosDataset[3]; cameraPosDataset[0]*=ratio; cameraPosDataset[1]*=ratio; cameraPosDataset[2]*=ratio; } cameraPosTexture[0] = (cameraPosDataset[0]-bounds[0])/dx; cameraPosTexture[1] = (cameraPosDataset[1]-bounds[2])/dy; cameraPosTexture[2] = (cameraPosDataset[2]-bounds[4])/dz; // Only make sense for the vectorial part of the homogeneous matrix. // coefMatrix=transposeWorldToTexture*worldToTexture // we re-cycle the datasetToWorld pointer with a different name vtkMatrix4x4 *transposeWorldToTexture=this->TempMatrix[1]; // transposeWorldToTexture={^t}worldToTexture vtkMatrix4x4::Transpose(worldToTexture,transposeWorldToTexture); vtkMatrix4x4 *coefMatrix=this->TempMatrix[1]; vtkMatrix4x4::Multiply4x4(transposeWorldToTexture,worldToTexture, coefMatrix); GLint uCameraPosition; uCameraPosition=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"cameraPosition"); if(uCameraPosition!=-1) { vtkgl::Uniform3f(uCameraPosition, static_cast(cameraPosTexture[0]), static_cast(cameraPosTexture[1]), static_cast(cameraPosTexture[2])); } else { vtkErrorMacro(<<"cameraPosition is not a uniform variable."); } GLint uSampleDistance; uSampleDistance=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"sampleDistance"); if(uSampleDistance!=-1) { vtkgl::Uniform1f(uSampleDistance,this->ActualSampleDistance); } else { vtkErrorMacro(<<"sampleDistance is not a uniform variable."); } GLint uMatrix1; uMatrix1=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"matrix1"); if(uMatrix1!=-1) { vtkgl::Uniform3f(uMatrix1, static_cast(coefMatrix->GetElement(0,0)), static_cast(coefMatrix->GetElement(1,1)), static_cast(coefMatrix->GetElement(2,2))); } else { vtkErrorMacro(<<"matrix1 is not a uniform variable."); } GLint uMatrix2; uMatrix2=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"matrix2"); if(uMatrix2!=-1) { vtkgl::Uniform3f(uMatrix2, static_cast(2*coefMatrix->GetElement(0,1)), static_cast(2*coefMatrix->GetElement(1,2)), static_cast(2*coefMatrix->GetElement(0,2))); } else { vtkErrorMacro(<<"matrix2 is not a uniform variable."); } } this->PrintError("after uniforms for projection"); // Change-of-coordinate matrix from Eye space to texture space. vtkMatrix4x4 *eyeToTexture=this->TempMatrix[1]; vtkMatrix4x4 *eyeToWorld=ren->GetActiveCamera()->GetViewTransformMatrix(); vtkMatrix4x4::Multiply4x4(eyeToWorld,worldToTexture,eyeToTexture); GLfloat matrix[16];// used sometimes as 3x3, sometimes as 4x4. double *raw=eyeToTexture->Element[0]; int index; int column; int row; int shadeMethod=this->LastShade; if(shadeMethod==vtkMitkOpenGLGPUVolumeRayCastMapperShadeYes) { index=0; column=0; while(column<3) { row=0; while(row<3) { // cout << "index=" << index << " row*4+column=" << row*4+column << endl; matrix[index]=static_cast(raw[row*4+column]); ++index; ++row; } ++column; } GLint uEyeToTexture3; uEyeToTexture3=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"eyeToTexture3"); this->PrintError("after getUniform eyeToTexture3"); if(uEyeToTexture3!=-1) { vtkgl::UniformMatrix3fv(uEyeToTexture3,1,GL_FALSE,matrix); } else { vtkErrorMacro(<<"eyeToTexture3 is not a uniform variable."); } this->PrintError("after Uniform eyeToTexture3"); index=0; column=0; while(column<4) { row=0; while(row<4) { // cout << "index=" << index << " row*4+column=" << row*4+column << endl; matrix[index]=static_cast(raw[row*4+column]); ++index; ++row; } ++column; } GLint uEyeToTexture4; uEyeToTexture4=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"eyeToTexture4"); if(uEyeToTexture4!=-1) { vtkgl::UniformMatrix4fv(uEyeToTexture4,1,GL_FALSE,matrix); } else { vtkErrorMacro(<<"eyeToTexture4 is not a uniform variable."); } } eyeToTexture->Invert(); index=0; column=0; while(column<4) { row=0; while(row<4) { // cout << "index=" << index << " row*4+column=" << row*4+column << endl; matrix[index]=static_cast(raw[row*4+column]); ++index; ++row; } ++column; } this->PrintError("before GetUniformLocation TextureToEye"); GLint uTextureToEye; uTextureToEye=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"textureToEye"); this->PrintError("after GetUniformLocation TextureToEye"); if(uTextureToEye!=-1) { vtkgl::UniformMatrix4fv(uTextureToEye,1,GL_FALSE,matrix); } else { vtkErrorMacro(<<"textureToEye is not a uniform variable."); } this->PrintError("after UniformMatrxix TextureToEye"); if(shadeMethod==vtkMitkOpenGLGPUVolumeRayCastMapperShadeYes) { eyeToTexture->Transpose(); index=0; column=0; while(column<3) { row=0; while(row<3) { // cout << "index=" << index << " row*4+column=" << row*4+column << endl; matrix[index]=static_cast(raw[row*4+column]); ++index; ++row; } ++column; } GLint uTranposeTextureToEye; uTranposeTextureToEye=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"transposeTextureToEye"); if(uTranposeTextureToEye!=-1) { vtkgl::UniformMatrix3fv(uTranposeTextureToEye,1,GL_FALSE,matrix); } else { vtkErrorMacro(<<"transposeTextureToEye is not a uniform variable."); } float cellScale[3]; // 1/(2*Step) float cellStep[3]; // Step vtkIdType *loadedExtent=this->CurrentScalar->GetLoadedExtent(); cellScale[0]=static_cast(static_cast( loadedExtent[1]-loadedExtent[0])*0.5); cellScale[1]=static_cast(static_cast( loadedExtent[3]-loadedExtent[2])*0.5); cellScale[2]=static_cast(static_cast( loadedExtent[5]-loadedExtent[4])*0.5); cellStep[0]=static_cast(1.0/static_cast( loadedExtent[1]-loadedExtent[0])); cellStep[1]=static_cast(1.0/static_cast( loadedExtent[3]-loadedExtent[2])); cellStep[2]=static_cast(1.0/static_cast( loadedExtent[5]-loadedExtent[4])); GLint uCellScale; uCellScale=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"cellScale"); if(uCellScale!=-1) { vtkgl::Uniform3f(uCellScale,cellScale[0],cellScale[1],cellScale[2]); } else { vtkErrorMacro(<<"error: cellScale is not a uniform variable."); } GLint uCellStep; uCellStep=vtkgl::GetUniformLocation( static_cast(this->ProgramShader),"cellStep"); if(uCellStep!=-1) { vtkgl::Uniform3f(uCellStep,cellStep[0],cellStep[1],cellStep[2]); } else { vtkErrorMacro(<<"error: cellStep is not a uniform variable."); } } } //----------------------------------------------------------------------------- // Concatenate the header string, projection type code and method to the // final fragment code in this->FragmentCode. // \pre valid_raycastMethod: raycastMethod>= // vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP && // raycastMethod<=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIPFourDependent //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::BuildProgram(int parallelProjection, int raycastMethod, int shadeMethod, int componentMethod) { assert("pre: valid_raycastMethod" && raycastMethod>= vtkMitkOpenGLGPUVolumeRayCastMapperMethodMIP && raycastMethod<=vtkMitkOpenGLGPUVolumeRayCastMapperMethodCompositeMask); GLuint fs; // cout<<"projection="<ProgramShader, vtkgl::INFO_LOG_LENGTH,¶ms); if(params>0) { char *buffer=new char[params]; vtkgl::GetProgramInfoLog(this->ProgramShader,params,0,buffer); cout<<"validation log: "<GetEnabledString(glIsEnabled(GL_LIGHTING))<GetEnabledString(glIsEnabled(GL_LIGHTING))<(value); cout<<"active texture is "<<(activeTexture-vtkgl::TEXTURE0)<(value); cout<<"light\t| status\t| ambient\t| diffuse\t| specular\t| position\t| spot direction\t| spot exponent\t| spot cutoff\t| k0\t| k1\t| k2"<=0 // \post valid_result: result>=x //----------------------------------------------------------------------------- int vtkMitkOpenGLGPUVolumeRayCastMapper::PowerOfTwoGreaterOrEqual(int x) { assert("pre: positive_x" && x>=0); int result=1; while(result=x); return result; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::UpdateNoiseTexture() { if(this->NoiseTextureId==0) { GLuint noiseTextureObject; glGenTextures(1,&noiseTextureObject); this->NoiseTextureId=static_cast(noiseTextureObject); vtkgl::ActiveTexture(vtkgl::TEXTURE6); glBindTexture(GL_TEXTURE_2D,noiseTextureObject); GLsizei size=128; // 1024; // Power of two value GLint maxSize; const float factor=0.1f; // const float factor=1.0f; const float amplitude=0.5f*factor; // something positive. // amplitude=0.5. noise between -0.5 +0.5. add some +0.5 shift. glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSize); if(size>maxSize) { size=maxSize; } if(this->NoiseTexture!=0 && this->NoiseTextureSize!=size) { delete[] this->NoiseTexture; this->NoiseTexture=0; } if(this->NoiseTexture==0) { this->NoiseTexture=new float[size*size]; this->NoiseTextureSize=size; vtkPerlinNoise *noiseGenerator=vtkPerlinNoise::New(); noiseGenerator->SetFrequency(size,1.0,1.0); noiseGenerator->SetPhase(0.0,0.0,0.0); noiseGenerator->SetAmplitude(amplitude); int j=0; while(jNoiseTexture[j*size+i]=0.0; //amplitude+static_cast(noiseGenerator->EvaluateFunction(i,j,0.0)); ++i; } ++j; } noiseGenerator->Delete(); } glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,size,size,0,GL_RED,GL_FLOAT, this->NoiseTexture); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); GLfloat borderColor[4]={0.0,0.0,0.0,0.0}; glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,borderColor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); vtkgl::ActiveTexture(vtkgl::TEXTURE0); } } // ---------------------------------------------------------------------------- // Description: // Return how much the dataset has to be reduced in each dimension to // fit on the GPU. If the value is 1.0, there is no need to reduce the // dataset. // \pre the calling thread has a current OpenGL context. // \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) // The computation is based on hardware limits (3D texture indexable size) // and MaxMemoryInBytes. // \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 // \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 // \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 void vtkMitkOpenGLGPUVolumeRayCastMapper::GetReductionRatio(double ratio[3]) { // Compute texture size int i; int wholeTextureExtent[6]; this->GetInput()->GetExtent(wholeTextureExtent); if(this->CellFlag) // if we deal with cell data { i=1; while(i<6) { wholeTextureExtent[i]--; i+=2; } } // Indexable hardware limits GLint maxSize; glGetIntegerv(vtkgl::MAX_3D_TEXTURE_SIZE,&maxSize); vtkIdType rTextureSize[3]; double dMaxSize=static_cast(maxSize); i=0; while(i<3) { double textureSize=wholeTextureExtent[2*i+1]-wholeTextureExtent[2*i]+1; if(textureSize>maxSize) { ratio[i]=dMaxSize/textureSize; } else { ratio[i]=1.0; // no reduction } rTextureSize[i]=static_cast(floor(textureSize*ratio[i])); ++i; } // Data memory limits. vtkDataArray *scalars=this->GetScalars(this->GetInput(),this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); int scalarType=scalars->GetDataType(); vtkIdType size=rTextureSize[0]*rTextureSize[1]*rTextureSize[2] *vtkAbstractArray::GetDataTypeSize(scalarType) *scalars->GetNumberOfComponents(); if(size>static_cast(this->MaxMemoryInBytes) *static_cast(this->MaxMemoryFraction)) { double r=static_cast(this->MaxMemoryInBytes) *static_cast(this->MaxMemoryFraction)/static_cast(size); double r3=pow(r,1.0/3.0); // try the keep reduction ratio uniform to avoid artifacts. bool reduced[3]; i=0; int count=0; while(i<3) { vtkIdType newSize=static_cast( floor(static_cast(rTextureSize[i])*r3)); reduced[i]=newSize>=1; if(reduced[i]) { ++count; } ++i; } if(count<3) // some axis cannot be reduced { double r2=sqrt(r); count=0; i=0; while(i<3) { if(reduced[i]) { vtkIdType newSize=static_cast( floor(static_cast(rTextureSize[i])*r2)); reduced[i]=newSize>=1; if(reduced[i]) { ++count; } } ++i; } if(count<2) // we can only reduce one axis { i=0; while(i<3) { if(reduced[i]) { ratio[i]*=r; } ++i; } } else // we can reduce two axes { i=0; while(i<3) { if(reduced[i]) { ratio[i]*=r2; } ++i; } } } else // we can reduce all three axes { i=0; while(i<3) { ratio[i]*=r3; ++i; } } } assert("post: valid_i_ratio" && ratio[0]>0 && ratio[0]<=1.0); assert("post: valid_j_ratio" && ratio[1]>0 && ratio[1]<=1.0); assert("post: valid_k_ratio" && ratio[2]>0 && ratio[2]<=1.0); } //----------------------------------------------------------------------------- // Standard print method //----------------------------------------------------------------------------- void vtkMitkOpenGLGPUVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } #endif \ No newline at end of file diff --git a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.h b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.h index cd0d5390ce..2d32613064 100644 --- a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.h +++ b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapper.h @@ -1,503 +1,518 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkOpenGLGPUVolumeRayCastMapper.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkMitkOpenGLGPUVolumeRayCastMapper - OpenGL subclass that draws the // image to the screen // .SECTION Description // This is the concrete implementation of a ray cast image display helper - // a helper class responsible for drawing the image to the screen. // .SECTION see also // vtkGPUVolumeRayCastMapper #ifndef __vtkMitkOpenGLGPUVolumeRayCastMapper_h #define __vtkMitkOpenGLGPUVolumeRayCastMapper_h #include "vtkMitkGPUVolumeRayCastMapper.h" #include "mitkCommon.h" #include "MitkExtExports.h" // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) class vtkVolume; class vtkRenderer; class vtkOpenGLExtensionManager; class vtkMatrix4x4; class vtkUnsupportedRequiredExtensionsStringStream; // Pimpl class vtkMapDataArrayTextureId; // Pimpl class vtkMapMaskTextureId; // Pimpl class vtkPolyData; class vtkClipConvexPolyData; class vtkClipPolyData; class vtkTessellatedBoxSource; class vtkOpacityTable; // internal class. class vtkRGBTable; // internal class. class vtkKWScalarField; // internal class. class vtkKWMask; // internal class. class vtkOpacityTables; // Pimpl class vtkDensifyPolyData; class vtkStdString; class MitkExt_EXPORT vtkMitkOpenGLGPUVolumeRayCastMapper : public vtkMitkGPUVolumeRayCastMapper { public: static vtkMitkOpenGLGPUVolumeRayCastMapper *New(); vtkTypeRevisionMacro(vtkMitkOpenGLGPUVolumeRayCastMapper,vtkMitkGPUVolumeRayCastMapper); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: // Based on hardware and properties, we may or may not be able to // render using 3D texture mapping. This indicates if 3D texture // mapping is supported by the hardware, and if the other extensions // necessary to support the specific properties are available. virtual int IsRenderSupported(vtkRenderWindow *window, vtkVolumeProperty *property); // Description: // Return a string matching the OpenGL errorCode. // \post result_exists: result!=0 static const char *OpenGLErrorMessage(unsigned int errorCode); // Description: // Display headerMessage on the standard output and the last OpenGL error // message if any. // \pre headerMessage_exists: headerMessage!=0 static void PrintError(const char *headerMessage); protected: vtkMitkOpenGLGPUVolumeRayCastMapper(); ~vtkMitkOpenGLGPUVolumeRayCastMapper(); // The render method called by the superclass virtual void GPURender(vtkRenderer *ren, vtkVolume *vol); // Methods called by the AMR Volume Mapper. virtual void PreRender(vtkRenderer *ren, vtkVolume *vol, double datasetBounds[6], double scalarRange[2], int numberOfScalarComponents, unsigned int numberOfLevels); // \pre input is up-to-date virtual void RenderBlock(vtkRenderer *ren, vtkVolume *vol, unsigned int level); virtual void PostRender(vtkRenderer *ren, int numberOfScalarComponents); // Description: // Return if the required OpenGL extension `extensionName' is supported. // If not, its name is added to the string of unsupported but required // extensions. // \pre extensions_exist: extensions!=0 // \pre extensionName_exists: extensionName!=0 int TestRequiredExtension(vtkOpenGLExtensionManager *extensions, const char *extensionName); // Description: // Attempt to load required and optional OpenGL extensions for the current // context window. Variable LoadExtensionsSucceeded is set if all required // extensions has been loaded. In addition, variable // Supports_GL_ARB_texture_float is set if this extension has been loaded. // \pre: window_exists: window!=0 void LoadExtensions(vtkRenderWindow *window); // Description: // Create GLSL OpenGL objects such fragment program Ids. void CreateGLSLObjects(); // Description: // Allows late binding textures to framebuffers, because ATI openGL requires // the texture to initialized before void BindFramebuffer(); // Description: // Create OpenGL objects such as textures, buffers and fragment program Ids. // It only registers Ids, there is no actual initialization of textures or // fragment program. // \pre extensions_loaded: this->LoadExtensionsSucceeded // \post done: this->OpenGLObjectsCreated==1 void CreateOpenGLObjects(); // Description: // Delete OpenGL objects. // \post done: this->OpenGLObjectsCreated==0 void ReleaseGraphicsResources(vtkWindow *window); // Description: // Allocate memory on the GPU for the framebuffers according to the size of // the window or reallocate if the size has changed. Return true if // allocation succeeded. // \pre ren_exists: ren!=0 // \pre opengl_objects_created: this->OpenGLObjectsCreated // \post right_size: LastSize[]=window size. int AllocateFrameBuffers(vtkRenderer *ren); // Description // Load the scalar field (one or four component scalar field), cell or point // based for a given subextent of the whole extent (can be the whole extent) // as a 3D texture on the GPU. // Extents are expressed in point if the cell flag is false or in cells of // the cell flag is true. // It returns true if it succeeded, false if there is not enough memory on // the GPU. // If succeeded, it updates the LoadedExtent, LoadedBounds, LoadedCellFlag // and LoadedTime. It also succeed if the scalar field is already loaded // (ie since last load, input has not changed and cell flag has not changed // and requested texture extents are enclosed in the loaded extent). // \pre input_exists: input!=0 // \pre valid_point_extent: (this->CellFlag || // (textureExtent[0]CellFlag || // (textureExtent[0]<=textureExtent[1] && // textureExtent[2]<=textureExtent[3] && // textureExtent[4]<=textureExtent[5]))) int LoadScalarField(vtkImageData *input, vtkImageData *maskInput, int textureExtent[6], vtkVolume *volume); // Description: // Allocate memory and load color table on the GPU or // reload it if the transfer function changed. // \pre vol_exists: vol!=0 // \pre valid_numberOfScalarComponents: numberOfScalarComponents==1 || numberOfScalarComponents==4 int UpdateColorTransferFunction(vtkVolume *vol, int numberOfScalarComponents); // Description: // Allocate memory and load opacity table on the GPU or // reload it if the transfer functions changed. // \pre vol_exists: vol!=0 // \pre valid_numberOfScalarComponents: numberOfScalarComponents==1 || numberOfScalarComponents==4 int UpdateOpacityTransferFunction(vtkVolume *vol, int numberOfScalarComponents, unsigned int level); // Description: // Prepare rendering in the offscreen framebuffer. // \pre ren_exists: ren!=0 // \pre vol_exists: vol!=0 void SetupRender(vtkRenderer *ren, vtkVolume *vol); // Description: // Clip the bounding box with all clipping planes // and the near and far plane void ClipBoundingBox(vtkRenderer *ren, double worldBounds[6], vtkVolume *vol); // Description: // Render the bounding box. The flag indicates whether // or not tcoords are rendered too. Return abort status (true==abort). // \pre valid_currentBlock: currentBlock>=0 && currentBlock=0 // \post valid_result: result>=x int PowerOfTwoGreaterOrEqual(int x); // Description: // Display the status of the current framebuffer on the standard output. void CheckFrameBufferStatus(); // Description: // Create a string from a buffer id. The result has to be free by the caller. vtkStdString BufferToString(int buffer); // Description: // Display the buffers assigned for drawing and reading operations. void DisplayReadAndDrawBuffers(); // Description: // Display all the attachments of the current framebuffer object. void DisplayFrameBufferAttachments(); // Description: // Display a given attachment for the current framebuffer object. void DisplayFrameBufferAttachment(unsigned int uattachment); // Description: // Concatenate the header string, projection type code and method to the // final fragment code in this->FragmentCode. // \pre valid_raycastMethod: raycastMethod>= vtkMitkOpenGLGPUVolumeRayCastMapperMethodMaximumIntensityProjection && raycastMethod<=vtkMitkOpenGLGPUVolumeRayCastMapperMethodMinIPFourDependent void BuildProgram(int parallelProjection, int raycastMethod, int shadeMethod, int componentMethod); // Description: // Return the current OpenGL state about lighting. void GetLightingStatus(); // Description: // Check the compilation status of some fragment shader source. void CheckCompilation(unsigned int fragmentShader); // Description: // Check the linkage status of the fragment program. int CheckLinkage(unsigned int programShader); // Description: // Print all active uniform variables void PrintUniformVariables(unsigned int programShader); // Description: // Is the program shader valid in the current OpenGL state? // Debugging purpose only. void ValidateProgram(); // Description: // Update the reduction factor of the render viewport (this->ReductionFactor) // according to the time spent in seconds to render the previous frame // (this->TimeToDraw) and a time in seconds allocated to render the next // frame (allocatedTime). // \pre valid_current_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 // \pre positive_TimeToDraw: this->TimeToDraw>=0.0 // \pre positive_time: allocatedTime>0 // \post valid_new_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 void ComputeReductionFactor(double allocatedTime); // Description: // Render a subvolume. // \pre this->ProgramShader!=0 and is linked. void RenderWholeVolume(vtkRenderer *ren, vtkVolume *vol); // Description: // Render a subvolume. // \pre this->ProgramShader!=0 and is linked. void RenderRegions(vtkRenderer *ren, vtkVolume *vol); // Return abort status (true==abort) int RenderSubVolume(vtkRenderer *ren, double bounds[6], vtkVolume *vol); void LoadProjectionParameters(vtkRenderer *ren, vtkVolume *vol); // Description: // Compute and return the number of cropping regions void ComputeNumberOfCroppingRegions(); void GetTextureFormat(vtkImageData *input, unsigned int *internalFormat, unsigned int *format, unsigned int *type, int *componentSize); bool TestLoadingScalar(unsigned int internalFormat, unsigned int format, unsigned int type, int textureSize[3], int componentSize); void SlabsFromDatasetToIndex(double slabsDataSet[6], double slabsPoints[6]); void SlabsFromIndexToDataset(double slabsPoints[6], double slabsDataSet[6]); const char *GetEnabledString(unsigned char value); void GetOpenGLState(); void DebugDisplayBox(vtkPolyData *box); void UpdateNoiseTexture(); // Description: // Compute how each axis of a cell is projected on the viewport in pixel. // This requires to have information about the camera and about the volume. // It set the value of IgnoreSampleDistancePerPixel to true in case of // degenerated case (axes aligned with the view). double ComputeMinimalSampleDistancePerPixel(vtkRenderer *renderer, vtkVolume *volume); // Description: // Return how much the dataset has to be reduced in each dimension to // fit on the GPU. If the value is 1.0, there is no need to reduce the // dataset. // \pre the calling thread has a current OpenGL context. // \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) // The computation is based on hardware limits (3D texture indexable size) // and MaxMemoryInBytes. // \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 // \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 // \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 virtual void GetReductionRatio(double ratio[3]); bool m_BindMax; int NumberOfCroppingRegions; // World coordinates of each corner of the dataset. double BoundingBox[8][3]; // Used during the clipping process. vtkPolyData *PolyDataBoundingBox; vtkPlaneCollection *Planes; vtkPlane *NearPlane; vtkClipConvexPolyData *Clip; vtkMatrix4x4 *InvVolumeMatrix; vtkDensifyPolyData *Densify; int OpenGLObjectsCreated; int NumberOfFrameBuffers; unsigned int FrameBufferObject; unsigned int DepthRenderBufferObject; // 3D scalar texture +1D color+1D opacity+2D grabbed depth buffer // +1 2D colorbuffer. unsigned int TextureObjects[5]; unsigned int FragmentMainShader; unsigned int FragmentProjectionShader; unsigned int FragmentTraceShader; unsigned int FragmentCroppingShader; unsigned int FragmentComponentShader; unsigned int FragmentShadeShader; unsigned int ProgramShader; // used in MIP Mode (2 needed for ping-pong technique) unsigned int MaxValueFrameBuffer; unsigned int MaxValueFrameBuffer2; int ReducedSize[2]; vtkPolyData *ClippedBoundingBox; int LastSize[2]; double ReductionFactor; // Supported extensions // List of unsupported required extensions. Pimpl. vtkUnsupportedRequiredExtensionsStringStream *UnsupportedRequiredExtensions; int LoadExtensionsSucceeded; int Supports_GL_ARB_texture_float; int SupportsPixelBufferObjects; vtkTimeStamp DataBufferTime; // Matrices used in internal computation. As a member variable, // only one memory allocation is performed. vtkMatrix4x4 *TempMatrix[3]; double TableRange[2]; // Final string to send to the GPU as the fragment program source code. // char *FragmentCode; // int FragmentCodeCapacity; int ErrorLine; int ErrorColumn; char *ErrorString; // Store the last projection an raycast method in order to not rebuild // the fragment code at every call. int LastParallelProjection; int LastRayCastMethod; int LastCroppingMode; int LastComponent; int LastShade; vtkImageData *SmallInput; vtkTimeStamp SmallInputBuildTime; // Description: // Build the fragment shader program that scale and bias a texture // for window/level purpose. void BuildScaleBiasProgram(); unsigned int ScaleBiasProgramShader; // GLuint int UFrameBufferTexture; // GLint int UScale; // GLint int UBias; // GLint #if 0 vtkIdType LoadedExtent[6]; double LoadedBounds[6]; vtkTimeStamp LoadedScalarTime; int LoadedCellFlag; // point data or cell data (or field data, not handled) ? #endif unsigned int SavedFrameBuffer; // some offscreen mode use a framebuffer too. vtkTessellatedBoxSource *BoxSource; float *NoiseTexture; int NoiseTextureSize; // size of one dimension. unsigned int NoiseTextureId; // GLuint bool IgnoreSampleDistancePerPixel; vtkMapDataArrayTextureId *ScalarsTextures; // need a list for AMR mode. vtkMapMaskTextureId *MaskTextures; // need a list for AMR mode. vtkRGBTable *RGBTable; vtkRGBTable *Mask1RGBTable; vtkRGBTable *Mask2RGBTable; vtkOpacityTables *OpacityTables; vtkKWScalarField *CurrentScalar; vtkKWMask *CurrentMask; float ActualSampleDistance; double LastProgressEventTime; // initial value is 0.0. Expressed in seconds. bool PreserveOrientation; private: vtkMitkOpenGLGPUVolumeRayCastMapper(const vtkMitkOpenGLGPUVolumeRayCastMapper&); // Not implemented. void operator=(const vtkMitkOpenGLGPUVolumeRayCastMapper&); // Not implemented. }; #endif #endif diff --git a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapperShaders.cpp b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapperShaders.cpp index 2303920226..ffa82705c9 100644 --- a/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapperShaders.cpp +++ b/Modules/MitkExt/Rendering/vtkMitkOpenGLGPUVolumeRayCastMapperShaders.cpp @@ -1,1799 +1,1814 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_CompositeCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_CompositeCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_CompositeCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_CompositeCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some function used by the composite method when cropping\n" "// is on.\n" "\n" "#version 110\n" "\n" "// color buffer as an input\n" "uniform sampler2D frameBufferTexture;\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "vec4 initialColor()\n" "{\n" " return texture2D(frameBufferTexture,fragTexCoord);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_CompositeFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_CompositeFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_CompositeFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_CompositeFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program part with ray cast and composite method.\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// from cropping vs no cropping\n" "vec4 initialColor();\n" "\n" "// from 1 vs 4 component shader.\n" "float scalarFromValue(vec4 value);\n" "vec4 colorFromValue(vec4 value);\n" "\n" "// from noshade vs shade.\n" "void initShade();\n" "vec4 shade(vec4 value);\n" "\n" "void trace(void)\n" "{\n" " vec4 destColor=initialColor();\n" " float remainOpacity=1.0-destColor.a;\n" "\n" " bool inside=true;\n" " \n" " vec4 color;\n" " vec4 opacity;\n" "\n" " initShade();\n" " \n" " float t=0.0;\n" " \n" " // We NEED two nested while loops. It is trick to work around hardware\n" " // limitation about the maximum number of loops.\n" "\n" " while(inside)\n" " { \n" " while(inside)\n" " {\n" " vec4 value=texture3D(dataSetTexture,pos);\n" " float scalar=scalarFromValue(value);\n" " // opacity is the sampled texture value in the 1D opacity texture at\n" " // scalarValue\n" " opacity=texture1D(opacityTexture,scalar);\n" " if(opacity.a>0.0)\n" " {\n" " color=shade(value);\n" " color=color*opacity.a;\n" " destColor=destColor+color*remainOpacity;\n" " remainOpacity=remainOpacity*(1.0-opacity.a);\n" " }\n" " pos=pos+rayDir;\n" " t+=1.0;\n" " inside=t=0.0039); // 1/255=0.0039\n" " }\n" " }\n" " gl_FragColor = destColor;\n" " gl_FragColor.a = 1.0-remainOpacity;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_CompositeMaskFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_CompositeMaskFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_CompositeMaskFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_CompositeMaskFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program part with ray cast and composite method with masks.\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler3D maskTexture;\n" "uniform sampler1D mask1ColorTexture;\n" "uniform sampler1D mask2ColorTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "uniform float maskBlendFactor;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// from cropping vs no cropping\n" "vec4 initialColor();\n" "\n" "// from 1 vs 4 component shader.\n" "float scalarFromValue(vec4 value);\n" "vec4 colorFromValue(vec4 value);\n" "\n" "// from noshade vs shade.\n" "void initShade();\n" "vec4 shade(vec4 value);\n" "\n" "void trace(void)\n" "{\n" " vec4 destColor=initialColor();\n" " float remainOpacity=1.0-destColor.a;\n" "\n" " bool inside=true;\n" " \n" " vec4 maskValue;\n" " vec4 color;\n" " vec4 opacity;\n" "\n" " initShade();\n" " \n" " float t=0.0;\n" " \n" " // We NEED two nested while loops. It is trick to work around hardware\n" " // limitation about the maximum number of loops.\n" "\n" " while(inside)\n" " { \n" " while(inside)\n" " {\n" " vec4 value=texture3D(dataSetTexture,pos);\n" " float scalar=scalarFromValue(value);\n" " opacity=texture1D(opacityTexture,scalar);\n" " \n" " if(maskBlendFactor==0.0)\n" " {\n" " color=shade(value);\n" " }\n" " else\n" " {\n" " // get the mask value at this same location\n" " maskValue=texture3D(maskTexture,pos);\n" " if(maskValue.a==0.0)\n" " {\n" " color=shade(value);\n" " }\n" " else\n" " {\n" " if(maskValue.a==1.0/255.0)\n" " {\n" " color=texture1D(mask1ColorTexture,scalar);\n" " }\n" " else\n" " {\n" " // maskValue.a == 2.0/255.0\n" " color=texture1D(mask2ColorTexture,scalar);\n" " }\n" " color.a=1.0;\n" " if(maskBlendFactor<1.0)\n" " {\n" " color=(1.0-maskBlendFactor)*shade(value)+maskBlendFactor*color;\n" " }\n" "// color.r = 1;\n" "// color.g = 0;\n" "// color.b = 0;\n" "// color.a = 1;\n" " }\n" " }\n" " \n" " color=color*opacity.a;\n" " destColor=destColor+color*remainOpacity;\n" " remainOpacity=remainOpacity*(1.0-opacity.a);\n" " \n" " pos=pos+rayDir;\n" " t+=1.0;\n" " inside=t=0.0039); // 1/255=0.0039\n" " }\n" " }\n" " gl_FragColor = destColor;\n" " gl_FragColor.a = 1.0-remainOpacity;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_CompositeNoCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_CompositeNoCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_CompositeNoCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_CompositeNoCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some function used by the composite method when cropping\n" "// is off.\n" "\n" "#version 110\n" "\n" "// Max intensity is the lowest value.\n" "vec4 initialColor()\n" "{\n" " return vec4(0.0,0.0,0.0,0.0);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the Minimum Intensity Projection\n" "// (MinIP) method when cropping is on.\n" "\n" "#version 110\n" "\n" "// GLSL Spec 1.10 rev 59 30-April-2004 defines gl_FragData[] but implementation\n" "// older than the spec only has it as an extension\n" "// (nVidia Linux driver 100.14.13, OpenGL version 2.1.1,\n" "// on Quadro FX 3500/PCI/SSE2)\n" "#extension GL_ARB_draw_buffers : enable\n" "\n" "// max scalar buffer as an input\n" "uniform sampler2D scalarBufferTexture;\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the scalar frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "float initialMinValue()\n" "{\n" " return texture2D(scalarBufferTexture,fragTexCoord).r;\n" "}\n" "\n" "void writeColorAndMinScalar(vec4 sample,\n" " vec4 opacity,\n" " float minValue)\n" "{\n" " // color framebuffer\n" " gl_FragData[0].r =sample.r * opacity.a;\n" " gl_FragData[0].g =sample.g * opacity.a;\n" " gl_FragData[0].b =sample.b * opacity.a;\n" " gl_FragData[0].a=opacity.a;\n" " \n" " // min scalar framebuffer\n" " gl_FragData[1].r=minValue;\n" " gl_FragData[1].g=0.0;\n" " gl_FragData[1].b=0.0;\n" " gl_FragData[1].a=0.0;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the 4-component Minimum Intensity\n" "// Projection (MinIP) method when cropping is on.\n" "\n" "#version 110\n" "\n" "// GLSL Spec 1.10 rev 59 30-April-2004 defines gl_FragData[] but implementation\n" "// older than the spec only has it as an extension\n" "// (nVidia Linux driver 100.14.13, OpenGL version 2.1.1,\n" "// on Quadro FX 3500/PCI/SSE2)\n" "#extension GL_ARB_draw_buffers : enable\n" "\n" "// max scalar buffer as an input\n" "uniform sampler2D scalarBufferTexture;\n" "\n" "// color buffer as an input\n" "uniform sampler2D frameBufferTexture;\n" "\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the scalar frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "float initialMinValue()\n" "{\n" " return texture2D(scalarBufferTexture,fragTexCoord).r;\n" "}\n" "\n" "vec4 initialColor()\n" "{\n" " return texture2D(frameBufferTexture,fragTexCoord);\n" "}\n" "\n" "void writeColorAndMinScalar(vec4 color,\n" " vec4 opacity,\n" " float minValue)\n" "{\n" " // color framebuffer\n" " gl_FragData[0].r = color.r*opacity.a;\n" " gl_FragData[0].g = color.g*opacity.a;\n" " gl_FragData[0].b = color.b*opacity.a;\n" " gl_FragData[0].a=opacity.a;\n" " \n" " // min scalar framebuffer\n" " gl_FragData[1].r=minValue;\n" " gl_FragData[1].g=0.0;\n" " gl_FragData[1].b=0.0;\n" " gl_FragData[1].a=0.0;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program with ray cast and 4-dependent-component Minimum Intensity\n" "// Projection (MinIP) method.\n" "// Compilation: header part and the projection part are inserted first.\n" "// pos is defined and initialized in header\n" "// rayDir is defined in header and initialized in the projection part\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// Sub-functions, depending on cropping mode\n" "float initialMinValue();\n" "vec4 initialColor();\n" "void writeColorAndMinScalar(vec4 color,\n" " vec4 opacity,\n" " float minValue);\n" "\n" "void trace(void)\n" "{\n" " // Max intensity is the lowest value.\n" " float minValue=initialMinValue();\n" " vec4 color=initialColor();\n" " bool inside=true;\n" " float t=0.0;\n" " vec4 sample;\n" " bool changed=false;\n" " \n" " // We NEED two nested while loops. It is a trick to work around hardware\n" " // limitation about the maximum number of loops.\n" " while(inside)\n" " {\n" " while(inside)\n" " {\n" " sample=texture3D(dataSetTexture,pos);\n" " if(sample.w=lowBounds.x && pos.y>=lowBounds.y\n" " && pos.z>=lowBounds.z && pos.x<=highBounds.x && pos.y<=highBounds.y\n" " && pos.z<=highBounds.z;\n" " }\n" " }\n" " \n" " if(changed)\n" " {\n" " vec4 opacity=texture1D(opacityTexture,minValue);\n" " writeColorAndMinScalar(color,opacity,minValue);\n" " }\n" " else\n" " {\n" " discard;\n" " }\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentNoCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentNoCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentNoCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPFourDependentNoCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the 4-component Minimum Intensity\n" "// Projection (MinIP) method when cropping is off.\n" "\n" "#version 110\n" "\n" "float initialMinValue()\n" "{\n" " return 1.0;\n" "}\n" "\n" "vec4 initialColor()\n" "{\n" " return vec4(0.0,0.0,0.0,0.0);\n" "}\n" "\n" "void writeColorAndMinScalar(vec4 color,\n" " vec4 opacity,\n" " float minValue)\n" "{\n" " // minValue is not used\n" " \n" " // color framebuffer\n" " gl_FragColor.r = color.r*opacity.a;\n" " gl_FragColor.g = color.g*opacity.a;\n" " gl_FragColor.b = color.b*opacity.a;\n" " gl_FragColor.a=opacity.a;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program with ray cast and Minimum Intensity Projection (MinIP)\n" "// method.\n" "// Compilation: header part and the projection part are inserted first.\n" "// pos is defined and initialized in header\n" "// rayDir is defined in header and initialized in the projection part\n" "// initMinValue() and writeColorAndMinScalar are defined in some specific\n" "// file depending on cropping flag being on or off.\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler1D colorTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// Sub-functions, depending on cropping mode\n" "float initialMinValue();\n" "void writeColorAndMinScalar(vec4 sample,\n" " vec4 opacity,\n" " float minValue);\n" "\n" "void trace(void)\n" "{\n" " // Max intensity is the lowest value.\n" " float minValue=initialMinValue();\n" " bool inside=true;\n" " vec4 sample;\n" " \n" " float t=0.0;\n" " // We NEED two nested while loops. It is trick to work around hardware\n" " // limitation about the maximum number of loops.\n" " while(inside)\n" " {\n" " while(inside)\n" " {\n" " sample=texture3D(dataSetTexture,pos);\n" " minValue=min(minValue,sample.r);\n" " pos=pos+rayDir;\n" " t+=1.0;\n" " inside=t=lowBounds.x && pos.y>=lowBounds.y\n" " && pos.z>=lowBounds.z && pos.x<=highBounds.x && pos.y<=highBounds.y\n" " && pos.z<=highBounds.z;\n" " \n" " \n" " }\n" " }\n" "\n" " sample=texture1D(colorTexture,minValue);\n" " vec4 opacity=texture1D(opacityTexture,minValue);\n" " \n" " writeColorAndMinScalar(sample,opacity,minValue);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MinIPNoCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MinIPNoCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MinIPNoCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MinIPNoCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the Minimum Intensity projection\n" "// (MinIP) method when cropping is off.\n" "\n" "#version 110\n" "\n" "float initialMinValue()\n" "{\n" " return 1.0;\n" "}\n" "\n" "void writeColorAndMinScalar(vec4 sample,\n" " vec4 opacity,\n" " float minValue)\n" "{\n" " // we don't need to write minValue to a buffer when there is no cropping.\n" " // color framebuffer\n" " gl_FragColor.r =sample.r * opacity.a;\n" " gl_FragColor.g =sample.g * opacity.a;\n" " gl_FragColor.b =sample.b * opacity.a;\n" " gl_FragColor.a=opacity.a;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the Maximum Intensity Projection\n" "// (MIP) method when cropping is on.\n" "\n" "#version 110\n" "\n" "// GLSL Spec 1.10 rev 59 30-April-2004 defines gl_FragData[] but implementation\n" "// older than the spec only has it as an extension\n" "// (nVidia Linux driver 100.14.13, OpenGL version 2.1.1,\n" "// on Quadro FX 3500/PCI/SSE2)\n" "#extension GL_ARB_draw_buffers : enable\n" "\n" "// max scalar buffer as an input\n" "uniform sampler2D scalarBufferTexture;\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the scalar frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "float initialMaxValue()\n" "{\n" " return texture2D(scalarBufferTexture,fragTexCoord).r;\n" "}\n" "\n" "void writeColorAndMaxScalar(vec4 sample,\n" " vec4 opacity,\n" " float maxValue)\n" "{\n" " // color framebuffer\n" " gl_FragData[0].r =sample.r * opacity.a;\n" " gl_FragData[0].g =sample.g * opacity.a;\n" " gl_FragData[0].b =sample.b * opacity.a;\n" " gl_FragData[0].a=opacity.a;\n" " \n" " // max scalar framebuffer\n" " gl_FragData[1].r=maxValue;\n" " gl_FragData[1].g=0.0;\n" " gl_FragData[1].b=0.0;\n" " gl_FragData[1].a=0.0;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPFourDependentCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPFourDependentCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPFourDependentCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the 4-component Maximum Intensity\n" "// Projection (MIP) method when cropping is on.\n" "\n" "#version 110\n" "\n" "// GLSL Spec 1.10 rev 59 30-April-2004 defines gl_FragData[] but implementation\n" "// older than the spec only has it as an extension\n" "// (nVidia Linux driver 100.14.13, OpenGL version 2.1.1,\n" "// on Quadro FX 3500/PCI/SSE2)\n" "#extension GL_ARB_draw_buffers : enable\n" "\n" "// max scalar buffer as an input\n" "uniform sampler2D scalarBufferTexture;\n" "\n" "// color buffer as an input\n" "uniform sampler2D frameBufferTexture;\n" "\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the scalar frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "float initialMaxValue()\n" "{\n" " return texture2D(scalarBufferTexture,fragTexCoord).r;\n" "}\n" "\n" "vec4 initialColor()\n" "{\n" " return texture2D(frameBufferTexture,fragTexCoord);\n" "}\n" "\n" "void writeColorAndMaxScalar(vec4 color,\n" " vec4 opacity,\n" " float maxValue)\n" "{\n" " // color framebuffer\n" " gl_FragData[0].r = color.r*opacity.a;\n" " gl_FragData[0].g = color.g*opacity.a;\n" " gl_FragData[0].b = color.b*opacity.a;\n" " gl_FragData[0].a=opacity.a;\n" " \n" " // max scalar framebuffer\n" " gl_FragData[1].r=maxValue;\n" " gl_FragData[1].g=0.0;\n" " gl_FragData[1].b=0.0;\n" " gl_FragData[1].a=0.0;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPFourDependentFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPFourDependentFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPFourDependentFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program with ray cast and 4-dependent-component Maximum Intensity\n" "// Projection (MIP) method.\n" "// Compilation: header part and the projection part are inserted first.\n" "// pos is defined and initialized in header\n" "// rayDir is defined in header and initialized in the projection part\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// Sub-functions, depending on cropping mode\n" "float initialMaxValue();\n" "vec4 initialColor();\n" "void writeColorAndMaxScalar(vec4 color,\n" " vec4 opacity,\n" " float maxValue);\n" "\n" "void trace(void)\n" "{\n" " // Max intensity is the lowest value.\n" " float maxValue=initialMaxValue();\n" " vec4 color=initialColor();\n" " bool inside=true;\n" " float t=0.0;\n" " vec4 sample;\n" " bool changed=false;\n" " \n" " // We NEED two nested while loops. It is a trick to work around hardware\n" " // limitation about the maximum number of loops.\n" " while(inside)\n" " {\n" " while(inside)\n" " {\n" " sample=texture3D(dataSetTexture,pos);\n" " if(sample.w>maxValue)\n" " {\n" " changed=true;\n" " maxValue=sample.w;\n" " color=sample;\n" " }\n" " pos=pos+rayDir;\n" " t+=1.0;\n" " \n" " // yes, t=lowBounds.x && pos.y>=lowBounds.y\n" " && pos.z>=lowBounds.z && pos.x<=highBounds.x && pos.y<=highBounds.y\n" " && pos.z<=highBounds.z;\n" " }\n" " }\n" " \n" " if(changed)\n" " {\n" " vec4 opacity=texture1D(opacityTexture,maxValue);\n" " writeColorAndMaxScalar(color,opacity,maxValue);\n" " }\n" " else\n" " {\n" " discard;\n" " }\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPFourDependentNoCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPFourDependentNoCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPFourDependentNoCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPFourDependentNoCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the 4-component Maximum Intensity\n" "// Projection (MIP) method when cropping is off.\n" "\n" "#version 110\n" "\n" "float initialMaxValue()\n" "{\n" " return 0.0;\n" "}\n" "\n" "vec4 initialColor()\n" "{\n" " return vec4(0.0,0.0,0.0,0.0);\n" "}\n" "\n" "void writeColorAndMaxScalar(vec4 color,\n" " vec4 opacity,\n" " float maxValue)\n" "{\n" " // maxValue is not used\n" " \n" " // color framebuffer\n" " gl_FragColor.r = color.r*opacity.a;\n" " gl_FragColor.g = color.g*opacity.a;\n" " gl_FragColor.b = color.b*opacity.a;\n" " gl_FragColor.a=opacity.a;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment program with ray cast and Maximum Intensity Projection (MIP)\n" "// method.\n" "// Compilation: header part and the projection part are inserted first.\n" "// pos is defined and initialized in header\n" "// rayDir is defined in header and initialized in the projection part\n" "// initMaxValue() and writeColorAndMaxScalar are defined in some specific\n" "// file depending on cropping flag being on or off.\n" "\n" "#version 110\n" "\n" "uniform sampler3D dataSetTexture;\n" "uniform sampler1D colorTexture;\n" "uniform sampler1D opacityTexture;\n" "\n" "uniform vec3 lowBounds;\n" "uniform vec3 highBounds;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "float tMax;\n" "\n" "// Sub-functions, depending on cropping mode\n" "float initialMaxValue();\n" "void writeColorAndMaxScalar(vec4 sample,\n" " vec4 opacity,\n" " float maxValue);\n" "\n" "void trace(void)\n" "{\n" " // Max intensity is the lowest value.\n" " float maxValue=initialMaxValue();\n" " bool inside=true;\n" " vec4 sample;\n" " \n" " float t=0.0;\n" " // We NEED two nested while loops. It is trick to work around hardware\n" " // limitation about the maximum number of loops.\n" " while(inside)\n" " {\n" " while(inside)\n" " {\n" " sample=texture3D(dataSetTexture,pos);\n" " maxValue=max(maxValue,sample.r);\n" " pos=pos+rayDir;\n" " t+=1.0;\n" " \n" " // yes, t=lowBounds.x && pos.y>=lowBounds.y\n" " && pos.z>=lowBounds.z && pos.x<=highBounds.x && pos.y<=highBounds.y\n" " && pos.z<=highBounds.z;\n" " }\n" " }\n" "\n" " sample=texture1D(colorTexture,maxValue);\n" " vec4 opacity=texture1D(opacityTexture,maxValue);\n" " \n" " writeColorAndMaxScalar(sample,opacity,maxValue);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_MIPNoCroppingFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_MIPNoCroppingFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_MIPNoCroppingFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_MIPNoCroppingFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Implementation of some functions used by the Maximum Intensity projection\n" "// (MIP) method when cropping is off.\n" "\n" "#version 110\n" "\n" "float initialMaxValue()\n" "{\n" " return 0.0;\n" "}\n" "\n" "void writeColorAndMaxScalar(vec4 sample,\n" " vec4 opacity,\n" " float maxValue)\n" "{\n" " // we don't need to write maxValue to a buffer when there is no cropping.\n" " // color framebuffer\n" " gl_FragColor.r =sample.r * opacity.a;\n" " gl_FragColor.g =sample.g * opacity.a;\n" " gl_FragColor.b =sample.b * opacity.a;\n" " gl_FragColor.a=opacity.a;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_OneComponentFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_OneComponentFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_OneComponentFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_OneComponentFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment shader that implements scalarFromValue() and colorFromValue() in\n" "// the case of a one-component dataset.\n" "// The functions are used in composite mode.\n" "\n" "#version 110\n" "\n" "// \"value\" is a sample of the dataset.\n" "// Think of \"value\" as an object.\n" "\n" "uniform sampler1D colorTexture;\n" "\n" "float scalarFromValue(vec4 value)\n" "{\n" " return value.x;\n" "}\n" "\n" "vec4 colorFromValue(vec4 value)\n" "{\n" " return texture1D(colorTexture,value.x);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_ParallelProjectionFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_ParallelProjectionFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_ParallelProjectionFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_ParallelProjectionFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Parallel projection.\n" "\n" "#version 110\n" "\n" "uniform vec3 parallelRayDirection;\n" "\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "// Defined in the right projection method.\n" "void incrementalRayDirection()\n" "{\n" " rayDir=parallelRayDirection;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_PerspectiveProjectionFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_PerspectiveProjectionFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_PerspectiveProjectionFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_PerspectiveProjectionFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Perspective projection.\n" "\n" "#version 110\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "// Camera position in texture space\n" "uniform vec3 cameraPosition;\n" "// Sample distance in world space\n" "uniform float sampleDistance;\n" "// Matrix coefficients: diagonal (a11,a22,a33)\n" "uniform vec3 matrix1;\n" "// Matrix coefficients: others (2a12,2a23,2a13)\n" "uniform vec3 matrix2;\n" "\n" "// Defined in the right projection method.\n" "void incrementalRayDirection()\n" "{\n" " // Direction of the ray in texture space, not normalized.\n" " rayDir=pos-cameraPosition;\n" " \n" " // x^2, y^2, z^2\n" " vec3 normDir=rayDir*rayDir;\n" " normDir.x=dot(normDir,matrix1);\n" " \n" " // xy,yz,zx\n" " vec3 coefs=rayDir*rayDir.yxz;\n" " coefs.x=dot(coefs,matrix2);\n" "\n" " // n^2\n" " normDir.x=normDir.x+coefs.x;\n" " \n" " // 1/n\n" " // normDir=1/sqrt(normDir)\n" " normDir.x=inversesqrt(normDir.x);\n" " \n" " // Final scale factor for the ray direction in texture space\n" " // normDir=normDir*sampleDistance\n" " normDir.x=normDir.x*sampleDistance;\n" " // Now, rayDir is the incremental direction in texture space\n" " rayDir=rayDir*normDir.x;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_ScaleBiasFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// This fragment shader scales and biases a framebuffer passed as a texture.\n" "// Incoming color from the texture is pre-multiplied by alpha.\n" "// It does not affect the alpha component.\n" "// Passing the framebuffer as a texture allows the use of a reduction factor\n" "// compared to the size of the final image.\n" "\n" "#version 110\n" "\n" "// Framebuffer to scale.\n" "uniform sampler2D frameBufferTexture;\n" "uniform float scale;\n" "uniform float bias;\n" "\n" "void main()\n" "{\n" " vec4 color=texture2D(frameBufferTexture,gl_TexCoord[0].xy);\n" " if(color.a==0.0)\n" " {\n" " discard;\n" " }\n" " // As incoming color is pre-multiplied by alpha, the bias has to be\n" " // multiplied by alpha before adding it.\n" " gl_FragColor.r=color.r*scale+bias*color.a;\n" " gl_FragColor.g=color.g*scale+bias*color.a;\n" " gl_FragColor.b=color.b*scale+bias*color.a;\n" " gl_FragColor.a=color.a;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_ShadeFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_ShadeFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_ShadeFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_ShadeFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "// Fragment shader that implements initShade() and shade() in the case of\n" "// shading.\n" "// The functions are used in composite mode.\n" "\n" "#version 110\n" "\n" "// \"value\" is a sample of the dataset.\n" "// Think of \"value\" as an object.\n" "\n" "// from 1- vs 4-component shader.\n" "vec4 colorFromValue(vec4 value);\n" "\n" "uniform sampler3D dataSetTexture; // need neighbors for gradient\n" "\n" "// Change-of-coordinate matrix from eye space to texture space\n" "uniform mat3 eyeToTexture3;\n" "uniform mat4 eyeToTexture4;\n" "\n" "// Tranpose of Change-of-coordinate matrix from texture space to eye space\n" "uniform mat3 transposeTextureToEye;\n" "\n" "// Used to compute the gradient.\n" "uniform vec3 cellStep;\n" "uniform vec3 cellScale;\n" "\n" "\n" "// Entry position (global scope), updated in the loop\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "\n" "// local to the implementation, shared between initShade() and shade()\n" "const vec3 minusOne=vec3(-1.0,-1.0,-1.0);\n" "const vec4 clampMin=vec4(0.0,0.0,0.0,0.0);\n" "const vec4 clampMax=vec4(1.0,1.0,1.0,1.0);\n" "\n" "vec3 xvec;\n" "vec3 yvec;\n" "vec3 zvec;\n" "vec3 wReverseRayDir;\n" "vec3 lightPos;\n" "vec3 ldir;\n" "vec3 h;\n" "vec4 hPos; // homogeneous position\n" "\n" "// ----------------------------------------------------------------------------\n" "void initShade()\n" "{\n" " xvec=vec3(cellStep.x,0.0,0.0); // 0.01\n" " yvec=vec3(0.0,cellStep.y,0.0);\n" " zvec=vec3(0.0,0.0,cellStep.z);\n" " \n" " // Reverse ray direction in eye space\n" " wReverseRayDir=eyeToTexture3*rayDir;\n" " wReverseRayDir=wReverseRayDir*minusOne;\n" " wReverseRayDir=normalize(wReverseRayDir);\n" " \n" " // Directonal light: w==0\n" " if(gl_LightSource[0].position.w==0.0)\n" " {\n" " ldir=gl_LightSource[0].position.xyz;\n" " ldir=normalize(ldir);\n" " h=normalize(ldir+wReverseRayDir);\n" " }\n" " else\n" " {\n" " lightPos=gl_LightSource[0].position.xyz/gl_LightSource[0].position.w;\n" " hPos.w=1.0; // used later\n" " }\n" "}\n" "\n" "// ----------------------------------------------------------------------------\n" "vec4 shade(vec4 value)\n" "{\n" " vec3 g1;\n" " vec3 g2;\n" " vec4 tmp;\n" " float att;\n" " float spot;\n" " \n" " g1.x=texture3D(dataSetTexture,pos+xvec).x;\n" " g1.y=texture3D(dataSetTexture,pos+yvec).x;\n" " g1.z=texture3D(dataSetTexture,pos+zvec).x;\n" " g2.x=texture3D(dataSetTexture,pos-xvec).x;\n" " g2.y=texture3D(dataSetTexture,pos-yvec).x;\n" " g2.z=texture3D(dataSetTexture,pos-zvec).x;\n" " // g1-g2 is the gradient in texture coordinates\n" " // the result is the normalized gradient in eye coordinates.\n" " \n" " g2=g1-g2;\n" " g2=g2*cellScale;\n" " \n" " float normalLength=length(g2);\n" " if(normalLength>0.0)\n" " {\n" " g2=normalize(transposeTextureToEye*g2);\n" " }\n" " else\n" " {\n" " g2=vec3(0.0,0.0,0.0);\n" " }\n" " \n" " vec4 color=colorFromValue(value);\n" " \n" " // initialize color to 0.0\n" " vec4 finalColor=vec4(0.0,0.0,0.0,0.0); \n" " \n" " if(gl_LightSource[0].position.w!=0.0)\n" " {\n" " // We need to know the eye position only if light is positional\n" " // ldir= vertex position in eye coordinates\n" " hPos.xyz=pos;\n" " tmp=eyeToTexture4*hPos;\n" " ldir=tmp.xyz/tmp.w;\n" " // ldir=light direction\n" " ldir=lightPos-ldir;\n" " float sqrDistance=dot(ldir,ldir);\n" " ldir=normalize(ldir);\n" " h=normalize(ldir+wReverseRayDir);\n" " att=1.0/(gl_LightSource[0].constantAttenuation+gl_LightSource[0].linearAttenuation*sqrt(sqrDistance)+gl_LightSource[0].quadraticAttenuation*sqrDistance);\n" " }\n" " else\n" " {\n" " att=1.0;\n" " }\n" " \n" " if(att>0.0)\n" " {\n" " if(gl_LightSource[0].spotCutoff==180.0)\n" " {\n" " spot=1.0;\n" " }\n" " else\n" " {\n" " float coef=-dot(ldir,gl_LightSource[0].spotDirection);\n" " if(coef>=gl_LightSource[0].spotCosCutoff)\n" " {\n" " spot=pow(coef,gl_LightSource[0].spotExponent);\n" " }\n" " else\n" " {\n" " spot=0.0;\n" " }\n" " }\n" " if(spot>0.0)\n" " {\n" " // LIT operation...\n" " float nDotL=dot(g2,ldir);\n" " float nDotH=dot(g2,h);\n" " \n" " // separate nDotL and nDotH for two-sided shading, otherwise we\n" " // get black spots.\n" " \n" " if(nDotL<0.0) // two-sided shading\n" " {\n" " nDotL=-nDotL;\n" " }\n" " \n" " if(nDotH<0.0) // two-sided shading\n" " {\n" " nDotH=-nDotH;\n" " }\n" " // ambient term for this light\n" " finalColor+=gl_FrontLightProduct[0].ambient;\n" " \n" " // diffuse term for this light\n" " if(nDotL>0.0)\n" " {\n" // WORKAROUND FIX: gl_FrontLightProduct[0].diffuse seems to be not transferred to ATI cards //" finalColor+=(gl_FrontLightProduct[0].diffuse*nDotL)*color;\n" // just using a white light now " finalColor+=(0.8*nDotL)*color;\n" " }\n" " \n" " // specular term for this light\n" " float shininessFactor=pow(nDotH,gl_FrontMaterial.shininess);\n" " finalColor+=gl_FrontLightProduct[0].specular*shininessFactor;\n" " finalColor*=att*spot;\n" " }\n" " }\n" " \n" " // scene ambient term\n" // WORKAROUND FIX: gl_FrontLightModelProduct.sceneColor seems to be not transferred to ATI cards //" finalColor+=gl_FrontLightModelProduct.sceneColor*color;\n" // just using a dim ambient light " finalColor+=0.3*color;\n" " \n" " // clamp. otherwise we get black spots\n" " finalColor=clamp(finalColor,clampMin,clampMax);\n" " \n" " return finalColor;\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_NoShadeFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_NoShadeFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_NoShadeFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_NoShadeFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment shader that implements initShade() and shade() in the case of no\n" "// shading.\n" "// The functions are used in composite mode.\n" "\n" "#version 110\n" "\n" "// \"value\" is a sample of the dataset.\n" "// Think of \"value\" as an object.\n" "\n" "// from 1- vs 4-component shader.\n" "vec4 colorFromValue(vec4 value);\n" "\n" "// ----------------------------------------------------------------------------\n" "void initShade()\n" "{\n" " // empty, nothing to do.\n" "}\n" "\n" "// ----------------------------------------------------------------------------\n" "vec4 shade(vec4 value)\n" "{\n" " return colorFromValue(value);\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_HeaderFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_HeaderFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_HeaderFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_HeaderFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "#version 110\n" "\n" "// Depth map of the polygonal geometry\n" "uniform sampler2D depthTexture;\n" "\n" "// 2D noise texture to jitter the starting point of the ray in order to\n" "// remove patterns when the opacity transfer function make the data on the\n" "// border of the dataset to be visible.\n" "uniform sampler2D noiseTexture;\n" "\n" "uniform vec2 windowLowerLeftCorner;\n" "uniform vec2 invOriginalWindowSize;\n" "uniform vec2 invWindowSize;\n" "\n" "// Change-of-coordinate matrix from eye space to texture space\n" "uniform mat4 textureToEye;\n" "\n" "// Entry position (global scope)\n" "vec3 pos;\n" "// Incremental vector in texture space (global scope)\n" "vec3 rayDir;\n" "\n" "// Abscissa along the ray of the point on the depth map\n" "// tracing stops when t>=tMax\n" "float tMax;\n" "\n" "// 2D Texture fragment coordinates [0,1] from fragment coordinates\n" "// the frame buffer texture has the size of the plain buffer but\n" "// we use a fraction of it. The texture coordinates is less than 1 if\n" "// the reduction factor is less than 1.\n" "vec2 fragTexCoord;\n" "\n" "// Defined in the right projection method.\n" "// May use pos in global scope as input.\n" "// Use rayDir in global scope as output.\n" "void incrementalRayDirection();\n" "void trace();\n" "\n" "void main()\n" "{\n" "\n" " // device coordinates are between -1 and 1\n" " // we need texture coordinates between 0 and 1\n" " // the depth buffer has the original size buffer.\n" " fragTexCoord=(gl_FragCoord.xy-windowLowerLeftCorner)*invWindowSize;\n" " vec4 depth=texture2D(depthTexture,fragTexCoord);\n" " if(gl_FragCoord.z>=depth.x) // depth test\n" " {\n" " discard;\n" " }\n" " \n" " // color buffer or max scalar buffer have a reduced size.\n" " fragTexCoord=(gl_FragCoord.xy-windowLowerLeftCorner)*invOriginalWindowSize;\n" " // Abscissa of the point on the depth buffer along the ray.\n" " // point in texture coordinates\n" " vec4 maxPoint;\n" " \n" " // from window coordinates to normalized device coordinates\n" " maxPoint.x=(gl_FragCoord.x-windowLowerLeftCorner.x)*2.0*invWindowSize.x-1.0;\n" " maxPoint.y=(gl_FragCoord.y-windowLowerLeftCorner.y)*2.0*invWindowSize.y-1.0;\n" " maxPoint.z=(2.0*depth.x-(gl_DepthRange.near+gl_DepthRange.far))/gl_DepthRange.diff;\n" " maxPoint.w=1.0;\n" " \n" " // from normalized device coordinates to eye coordinates\n" " maxPoint=gl_ProjectionMatrixInverse*maxPoint;\n" " \n" " // from eye coordinates to texture coordinates\n" " maxPoint=textureToEye*maxPoint;\n" " // homogeneous to cartesian coordinates\n" " maxPoint/=maxPoint.w;\n" " \n" " // Entry position. divide by q.\n" " // pos=gl_TexCoord[0].xyz/gl_TexCoord[0].w;\n" " \n" " pos.x=gl_TexCoord[0].x/gl_TexCoord[0].w;\n" " pos.y=gl_TexCoord[0].y/gl_TexCoord[0].w;\n" " pos.z=gl_TexCoord[0].z/gl_TexCoord[0].w;\n" " \n" " // Incremental vector in texture space. Computation depends on the\n" " // type of projection (parallel or perspective)\n" " incrementalRayDirection();\n" " \n" " vec4 noiseValue=texture2D(noiseTexture,pos.xy*100.0); // with repeat/tiling mode on the noise texture.\n" " \n" " pos+=(noiseValue.x)*rayDir;\n" "\n" " tMax=length(maxPoint.xyz-pos.xyz) /length(rayDir);\n" "\n" "\n" " // Tracing method. Set the final fragment color.\n" " trace();\n" "}\n" "\n"; /* DO NOT EDIT. * Generated by ..\bin\Release\vtkEncodeString.exe * * Define the vtkMitkGPUVolumeRayCastMapper_FourComponentsFS string. * * Generated from file: V:/windows/source/VTK560/VolumeRendering/vtkMitkGPUVolumeRayCastMapper_FourComponentsFS.glsl */ const char *vtkMitkGPUVolumeRayCastMapper_FourComponentsFS = "/*=========================================================================\n" "\n" " Program: Visualization Toolkit\n" " Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper_FourComponentsFS.glsl,v $\n" "\n" " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n" " All rights reserved.\n" " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n" "\n" " This software is distributed WITHOUT ANY WARRANTY; without even\n" " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" " PURPOSE. See the above copyright notice for more information.\n" "\n" "=========================================================================*/\n" "\n" "// Fragment shader that implements scalarFromValue() and colorFromValue() in\n" "// the case of a one-component dataset.\n" "// The functions are used in composite mode.\n" "\n" "#version 110\n" "\n" "// \"value\" is a sample of the dataset.\n" "// Think of \"value\" as an object.\n" "\n" "float scalarFromValue(vec4 value)\n" "{\n" " return value.w;\n" "}\n" "\n" "vec4 colorFromValue(vec4 value)\n" "{\n" " return vec4(value.xyz,1.0);\n" "}\n" "\n"; #endif \ No newline at end of file diff --git a/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h b/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h index 30e6e54532..83fc159842 100644 --- a/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h +++ b/Modules/OpenCVVideoSupport/mitkOpenCVImageSource.h @@ -1,27 +1,42 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKOPENCVIMAGESOURCE_H #define MITKOPENCVIMAGESOURCE_H #include #include namespace mitk { /// /// interface for a class providing opencv images /// class OpenCVImageSource: virtual public itk::Object { public: /// /// provide smart pointer defs /// mitkClassMacro( OpenCVImageSource, itk::Object ); /// /// \return a image as opencv 2 Mat /// virtual cv::Mat GetImage() = 0; }; } #endif // MITKOPENCVIMAGESOURCE_H diff --git a/Modules/OpenCVVideoSupport/mitkVideoInputSource.cpp b/Modules/OpenCVVideoSupport/mitkVideoInputSource.cpp index b6093df8e0..ac70b1feab 100644 --- a/Modules/OpenCVVideoSupport/mitkVideoInputSource.cpp +++ b/Modules/OpenCVVideoSupport/mitkVideoInputSource.cpp @@ -1,92 +1,107 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkVideoInputSource.h" #include #include #include mitk::VideoInputSource::VideoInputSource() : m_ShowSettingsWindow(false) { m_CaptureWidth = 1900; m_CaptureHeight = 1080; m_CapturingInProcess = false; m_DeviceNumber = -1; m_CaptureSize = 0; m_CurrentVideoTexture = NULL; m_CurrentImage = NULL; m_VideoInput = new videoInput; m_UndistortImage = false; } mitk::VideoInputSource::~VideoInputSource() { delete m_VideoInput; } void mitk::VideoInputSource::FetchFrame() { // main procedure for updating video data // if(m_CurrentVideoTexture == NULL) // m_CurrentVideoTexture = new unsigned char[m_CaptureSize]; if(m_CapturingInProcess && !m_CapturePaused) { if(m_CurrentImage == NULL) m_CurrentImage = cvCreateImage(cvSize(m_CaptureWidth,m_CaptureHeight),IPL_DEPTH_8U,3); if(m_VideoInput->isFrameNew(m_DeviceNumber)) { //m_VideoInput->getPixels(m_DeviceNumber, m_CurrentVideoTexture, true, false); m_VideoInput->getPixels(m_DeviceNumber, reinterpret_cast(m_CurrentImage->imageData), false, true); // only undistort if not paused if(m_UndistortImage && m_UndistortCameraImage.IsNotNull()) m_UndistortCameraImage->UndistortImageFast(m_CurrentImage, 0); } } } void mitk::VideoInputSource::StartCapturing() { //Prints out a list of available devices and returns num of devices found int numDevices = m_VideoInput->listDevices(); m_VideoInput->setupDevice(m_DeviceNumber, m_CaptureWidth, m_CaptureHeight); //to get a settings dialog for the device if(m_ShowSettingsWindow) m_VideoInput->showSettingsWindow(m_DeviceNumber); //As requested width and height can not always be accomodated //make sure to check the size once the device is setup m_CaptureWidth = m_VideoInput->getWidth(m_DeviceNumber); m_CaptureHeight = m_VideoInput->getHeight(m_DeviceNumber); m_CaptureSize = m_VideoInput->getSize(m_DeviceNumber); MITK_INFO << "starting capturing with VideoInputLib. Size: " << m_CaptureWidth << " x " << m_CaptureHeight; m_CapturingInProcess = true; } void mitk::VideoInputSource::StopCapturing() { m_VideoInput->stopDevice(m_DeviceNumber); m_CapturingInProcess = false; } void mitk::VideoInputSource::SetVideoCameraInput(int cameraindex, bool useCVCAMLib) { m_DeviceNumber = cameraindex; } void mitk::VideoInputSource::SetVideoFileInput(const char * filename, bool repeatVideo, bool useCVCAMLib) { } diff --git a/Modules/OpenCVVideoSupport/mitkVideoInputSource.h b/Modules/OpenCVVideoSupport/mitkVideoInputSource.h index 0bcaa9ca8e..b6225b0d36 100644 --- a/Modules/OpenCVVideoSupport/mitkVideoInputSource.h +++ b/Modules/OpenCVVideoSupport/mitkVideoInputSource.h @@ -1,62 +1,77 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _mitk_VideoInput_Source_h_ #define _mitk_VideoInput_Source_h_ #include "mitkConfig.h" #include "mitkOpenCVVideoSource.h" #include "mitkUndistortCameraImage.h" #include #include "cv.h" // open CV class videoInput; namespace mitk { class MITK_OPENCVVIDEOSUPPORT_EXPORT VideoInputSource : public OpenCVVideoSource { public: mitkClassMacro( VideoInputSource, OpenCVVideoSource ); itkNewMacro( Self ); ////##Documentation ////## @brief All functions behave like OpenCVVideoSource to the outside. //void GetCurrentFrameAsOpenCVImage(IplImage * image); void FetchFrame(); ////##Documentation ////## @brief returns a pointer to the image data array for opengl rendering. //unsigned char * GetVideoTexture(); void StartCapturing(); void StopCapturing(); void SetVideoCameraInput(int cameraindex, bool useCVCAMLib); void SetVideoFileInput(const char * filename, bool repeatVideo, bool useCVCAMLib); itkGetConstMacro(ShowSettingsWindow, bool); itkSetMacro(ShowSettingsWindow, bool); itkGetMacro(VideoInput, bool); protected: VideoInputSource(); virtual ~VideoInputSource(); videoInput* m_VideoInput; int m_DeviceNumber; int m_CaptureSize; // current Video image unsigned char* m_CurrentVideoTexture; /// /// Show vendor specific settings window? /// bool m_ShowSettingsWindow; }; } #endif // Header diff --git a/Modules/Overlays/QmitkCustomWidgetOverlay.cpp b/Modules/Overlays/QmitkCustomWidgetOverlay.cpp new file mode 100644 index 0000000000..fa233291dd --- /dev/null +++ b/Modules/Overlays/QmitkCustomWidgetOverlay.cpp @@ -0,0 +1,41 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2010-01-14 14:20:26 +0100 (Thu, 14 Jan 2010) $ +Version: $Revision: 21047 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "QmitkCustomWidgetOverlay.h" + + +QmitkCustomWidgetOverlay::QmitkCustomWidgetOverlay( const char* id ) +: QmitkOverlay(id) +{ + QmitkOverlay::AddDropShadow( m_Widget ); +} + +QmitkCustomWidgetOverlay::~QmitkCustomWidgetOverlay() +{ +} + +void QmitkCustomWidgetOverlay::SetWidget( QWidget* widget ) +{ + if ( widget != NULL ) + { + m_Widget = widget; + m_WidgetIsCustom = true; + } +} + + + diff --git a/Modules/Overlays/QmitkCustomWidgetOverlay.h b/Modules/Overlays/QmitkCustomWidgetOverlay.h new file mode 100644 index 0000000000..e9c50220e3 --- /dev/null +++ b/Modules/Overlays/QmitkCustomWidgetOverlay.h @@ -0,0 +1,65 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-05-28 17:19:30 +0200 (Thu, 28 May 2009) $ +Version: $Revision: 17495 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef QmitkCustomWidgetOverlay_H_HEADER_INCLUDED_C10DC4EB +#define QmitkCustomWidgetOverlay_H_HEADER_INCLUDED_C10DC4EB + +// MITK +#include "QmitkOverlay.h" + +#include "OverlaysExports.h" + + +/** \class QmitkCustomWidgetOverlay +* \brief object representing a custom widget that is handled and positioned +* as an overlay. +* +* A QmitkCustomWidgetOverlay is a generic sub-class of QmitkOverlay. It +* offers the possibility to set the internal m_Widget from the outside. +* +* This offers the possibility to position custom widgets 'on top of' other +* widgets using the positioning mechanism of all overlays. +* +* \warn The custom widgets need to be configured and connected manually. +* Properties cannot be set. +* +* \ingroup Overlays +*/ + + + class Overlays_EXPORT QmitkCustomWidgetOverlay : public QmitkOverlay + { + public: + + /** + * @brief Default Constructor + **/ + QmitkCustomWidgetOverlay( const char* id ); + + /** + * @brief Default Destructor + **/ + virtual ~QmitkCustomWidgetOverlay(); + + void SetWidget( QWidget* widget ); + + }; + + +#endif /* QmitkCustomWidgetOverlay_H_HEADER_INCLUDED_C10DC4EB */ + diff --git a/Modules/Overlays/QmitkOverlay.cpp b/Modules/Overlays/QmitkOverlay.cpp index 27c054f2b6..c1b356ff34 100644 --- a/Modules/Overlays/QmitkOverlay.cpp +++ b/Modules/Overlays/QmitkOverlay.cpp @@ -1,78 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkOverlay.h" #include #include QmitkOverlay::QmitkOverlay( const char* id ) :QObject() , m_Id(id) , m_Position(top_Left) , m_Layer(-1) , m_Widget(NULL) +, m_WidgetIsCustom(false) { } QmitkOverlay::~QmitkOverlay() { - if (m_Widget) + if ( m_Widget && !m_WidgetIsCustom ) { m_Widget->deleteLater(); m_Widget = NULL; } } QmitkOverlay::DisplayPosition QmitkOverlay::GetPosition() { return m_Position; } void QmitkOverlay::SetPosition( DisplayPosition pos ) { m_Position = pos; } unsigned int QmitkOverlay::GetLayer() { return m_Layer; } void QmitkOverlay::SetLayer( unsigned int layer ) { m_Layer = layer; } QWidget* QmitkOverlay::GetWidget() { return m_Widget; } void QmitkOverlay::AddDropShadow( QWidget* widget ) { - QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(widget); - effect->setOffset( QPointF( 1.0, 1.0 ) ); - effect->setBlurRadius( 0 ); - effect->setColor( Qt::black ); - - widget->setGraphicsEffect( effect ); + if (m_Widget) + { + QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(widget); + effect->setOffset( QPointF( 1.0, 1.0 ) ); + effect->setBlurRadius( 0 ); + effect->setColor( Qt::black ); + + widget->setGraphicsEffect( effect ); + } } diff --git a/Modules/Overlays/QmitkOverlay.h b/Modules/Overlays/QmitkOverlay.h index 5824163472..503a17f7a3 100644 --- a/Modules/Overlays/QmitkOverlay.h +++ b/Modules/Overlays/QmitkOverlay.h @@ -1,129 +1,131 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKOVERLAY_H_HEADER_INCLUDED_C10DC4EB #define MITKOVERLAY_H_HEADER_INCLUDED_C10DC4EB // MITK #include "mitkCommon.h" #include "mitkPropertyList.h" // Qt #include #include "OverlaysExports.h" /** \brief Abstract base class for all overlay-objects in MITK This class is the basis for all classes representing objects that can be visualized as overlays in MITK. It encapsulates an ID, as well as a display-position and a layer. The ID is used to access mitkProperties in a PropertyList that holds information that is needed for the visualization, e.g. text for TextOverlays or scaleFactor for ScalarBarOverlays ... The display-position encodes where on the screen the overlay will be positioned at (see and USE the constants defined by DisplayPosition): \verbatim 0 - 1 - 2 | | | 3 - - 4 | | | 5 - 6 - 7 \endverbatim The layer is needed if several overlays shall be put in the same position. In this case the layer defines the order in which the objects are layouted. \ingroup Qmitk */ class Overlays_EXPORT QmitkOverlay : public QObject { Q_OBJECT public: /** \brief enumeration of all possible display positions */ enum DisplayPosition { top_Left = 0, top_Center = 1, top_Right = 2, middle_Left = 3, middle_Right = 4, bottom_Left = 5, bottom_Center = 6, bottom_Right = 7 }; /** * @brief Constructor with string ID **/ QmitkOverlay(const char* id); /** * @brief Default Destructor **/ virtual ~QmitkOverlay(); /** \brief setter for the display-position */ virtual void SetPosition( DisplayPosition ); /** \brief getter for the display-position */ virtual DisplayPosition GetPosition(); /** \brief setter for the layer */ virtual void SetLayer( unsigned int ); /** \brief getter for the layer */ virtual unsigned int GetLayer(); /** * \brief abstract method to internally setup the overlay */ virtual void GenerateData( mitk::PropertyList::Pointer /*pl*/ ) {}; /** * \brief returns the internally handled QWidget */ virtual QWidget* GetWidget(); protected: /** \brief Add drop shadow effect via QGraphicsEffect */ void AddDropShadow( QWidget* widget ); /** \brief ID of the overlay */ const char* m_Id; /** \brief position of the overlay */ DisplayPosition m_Position; /** \brief layer of the overlay */ unsigned int m_Layer; /** \brief internal QWidget representing the overlay */ QWidget* m_Widget; + + bool m_WidgetIsCustom; }; #endif /* MITKOVERLAY_H_HEADER_INCLUDED_C10DC4EB */ diff --git a/Modules/Overlays/QmitkOverlayController.cpp b/Modules/Overlays/QmitkOverlayController.cpp index 99d71766b7..8873301a7f 100644 --- a/Modules/Overlays/QmitkOverlayController.cpp +++ b/Modules/Overlays/QmitkOverlayController.cpp @@ -1,406 +1,403 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkOverlayController.h" #include "QmitkRenderWindow.h" #include "QmitkOverlay.h" #include #include #include QmitkOverlayController::QmitkOverlayController( QmitkRenderWindow* rw, mitk::PropertyList* pl ) : QObject(), m_RenderWindow( rw ), m_PropertyList( pl ) { if ( m_RenderWindow == NULL ) { MITK_ERROR << "invalid QmitkRenderWindow"; return; } connect( rw, SIGNAL( moved() ), this, SLOT( AdjustOverlayPosition() ) ); this->InitializeOverlayLayout(); this->AdjustOverlayPosition(); this->SetOverlayVisibility( true ); if ( m_PropertyList.IsNull() ) m_PropertyList = mitk::PropertyList::New(); } QmitkOverlayController::~QmitkOverlayController() { } void QmitkOverlayController::InitializeOverlayLayout() { // setup widget for each position this->InitializeWidget( QmitkOverlay::top_Left ); this->InitializeWidget( QmitkOverlay::top_Center ); this->InitializeWidget( QmitkOverlay::top_Right ); this->InitializeWidget( QmitkOverlay::middle_Left ); this->InitializeWidget( QmitkOverlay::middle_Right ); this->InitializeWidget( QmitkOverlay::bottom_Left ); this->InitializeWidget( QmitkOverlay::bottom_Center ); this->InitializeWidget( QmitkOverlay::bottom_Right ); } void QmitkOverlayController::InitializeWidget( QmitkOverlay::DisplayPosition pos ) { // create a new QWidget as Tool & FramelessWindowHint m_PositionedOverlays[ pos ] = new QWidget( m_RenderWindow, Qt::Tool | Qt::FramelessWindowHint ); // autoFillBackGround(false) and WA_TranslucentBackground = true are needed to have a translucent background // transparency does NOT work under Win-XP 32-Bit --> paint black background #if !defined(_WIN32) || defined(_WIN64) m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_TranslucentBackground, true ); #else m_PositionedOverlays[ pos ]->setStyleSheet( "QWidget { background: black }" ); m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_TranslucentBackground, false ); #endif // X11 specific attributes m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_X11NetWmWindowTypeUtility, true ); // mac-specific attributes: // making sure overlays are even visible if RenderWindow does not have the focus (not default for Qt::Tool on mac) m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_MacAlwaysShowToolWindow, true ); // testing something m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_MacShowFocusRect, false ); // overlays should not get the focus m_PositionedOverlays[ pos ]->setFocusPolicy( Qt::NoFocus ); // setting the color of the background to transparent - not sure it's needed after the attributes have been set above QPalette p = QPalette(); p.setColor( QPalette::Window, Qt::transparent ); m_PositionedOverlays[ pos ]->setPalette( p ); // setting position-specific properties switch ( pos ) { case QmitkOverlay::top_Left : { // adding left-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::top_Center : { // adding center-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignCenter ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::top_Right : { // adding right-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignRight ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::middle_Left : { // adding left-aligned left-to-right layout QHBoxLayout* layout = new QHBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::LeftToRight ); layout->setAlignment( Qt::AlignLeft ); layout->setSpacing( 3 ); break; } case QmitkOverlay::middle_Right : { // adding right-aligned right-to-left layout QHBoxLayout* layout = new QHBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::RightToLeft ); layout->setAlignment( Qt::AlignRight ); layout->setSpacing( 3 ); break; } case QmitkOverlay::bottom_Left : { // adding left-aligned bottom-to-top layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::bottom_Center : { QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignCenter ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::bottom_Right : { QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignRight ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } } } void QmitkOverlayController::AdjustOverlayPosition() { + QWidget* widget; + QPoint pos; + // setting position of top-left overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::top_Left ]->isVisible() ) - { - QPoint pos = m_RenderWindow->mapToGlobal( QPoint(0,0) ); - m_PositionedOverlays[ QmitkOverlay::top_Left ]->move( pos.x(), pos.y() ); - } + pos = m_RenderWindow->mapToGlobal( QPoint(0,0) ); + m_PositionedOverlays[ QmitkOverlay::top_Left ]->move( pos.x(), pos.y() ); + // setting position of top-center overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::top_Center ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::top_Center ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, 0 ) ) ; - widget->move( pos.x() - widget->size().width()/2, pos.y() ); - } + widget = m_PositionedOverlays[ QmitkOverlay::top_Center ]; + pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, 0 ) ) ; + widget->move( pos.x() - widget->size().width()/2, pos.y() ); + // setting position of top-right overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::top_Right ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::top_Right ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), 0 ) ) ; - widget->move( pos.x() - widget->size().width(), pos.y() ); - } + widget = m_PositionedOverlays[ QmitkOverlay::top_Right ]; + pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), 0 ) ) ; + widget->move( pos.x() - widget->size().width(), pos.y() ); + // setting position of middle-left overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::middle_Left ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::middle_Left ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height()/2 ) ) ; - widget->move( pos.x(), pos.y() - widget->size().height()/2 ); - } + widget = m_PositionedOverlays[ QmitkOverlay::middle_Left ]; + pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height()/2 ) ) ; + widget->move( pos.x(), pos.y() - widget->size().height()/2 ); + // setting position of middle-right overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::middle_Right ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::middle_Right ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height()/2 ) ) ; - widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height()/2 ); - } + widget = m_PositionedOverlays[ QmitkOverlay::middle_Right ]; + pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height()/2 ) ) ; + widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height()/2 ); + // setting position of bottom-left overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::bottom_Left ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::bottom_Left ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height() ) ) ; - widget->move( pos.x(), pos.y() - widget->size().height() ); - } + widget = m_PositionedOverlays[ QmitkOverlay::bottom_Left ]; + pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height() ) ) ; + widget->move( pos.x(), pos.y() - widget->size().height() ); + // setting position of bottom-center overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::bottom_Center ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::bottom_Center ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, m_RenderWindow->size().height() ) ) ; - widget->move( pos.x() - widget->size().width()/2, pos.y() - widget->size().height() ); - } + widget = m_PositionedOverlays[ QmitkOverlay::bottom_Center ]; + pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, m_RenderWindow->size().height() ) ) ; + widget->move( pos.x() - widget->size().width()/2, pos.y() - widget->size().height() ); - // setting position of bottom-right overlay-container - if ( m_PositionedOverlays[ QmitkOverlay::bottom_Right ]->isVisible() ) - { - QWidget* widget = m_PositionedOverlays[ QmitkOverlay::bottom_Right ]; - QPoint pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height() ) ) ; - widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height() ); - } + // setting position of bottom-right overlay-container + widget = m_PositionedOverlays[ QmitkOverlay::bottom_Right ]; + pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height() ) ) ; + widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height() ); } void QmitkOverlayController::SetOverlayVisibility( bool visible ) { - // setting visibility of all registered overlays to 'visible' - foreach( QmitkOverlay* overlay, m_AllOverlays ) + OverlayPositionMap::iterator overlayIter; + for ( overlayIter=m_PositionedOverlays.begin(); overlayIter!=m_PositionedOverlays.end(); overlayIter++ ) { if ( visible ) { - overlay->GetWidget()->show(); + (overlayIter->second)->show(); } else { - overlay->GetWidget()->hide(); + (overlayIter->second)->hide(); + } + } + + OverlayVector::iterator allOverlaysIter; + for( allOverlaysIter=m_AllOverlays.begin(); allOverlaysIter!=m_AllOverlays.end(); allOverlaysIter++ ) + { + if ( visible ) + { + (*allOverlaysIter)->GetWidget()->show(); } + else + { + (*allOverlaysIter)->GetWidget()->hide(); + } + } } void QmitkOverlayController::AddOverlay( QmitkOverlay* overlay ) { // if no renderwindow has been set, it's not possible to add overlays... if ( m_RenderWindow == NULL ) { MITK_ERROR << "invalid QmitkRenderWindow"; return; } if ( overlay != NULL ) { // get desired position and layer of the overlay QmitkOverlay::DisplayPosition pos = overlay->GetPosition(); // concatenate local propertyList and propertyList of the RenderingManager // local properties have priority as they are not overwritten if preset in both m_PropertyList->ConcatenatePropertyList( m_RenderWindow->GetRenderer()->GetRenderingManager()->GetPropertyList(), false ); // add the overlay to the OverlayContainer in the RenderWindow ... overlay->GetWidget()->setParent( m_PositionedOverlays[ pos ] ); // ... and set it up with the correct properties this->UpdateOverlayData( overlay ); // add overlay to list of all overlays and correctly put it into the layering m_AllOverlays.push_back( overlay ); this->RestackOverlays( pos ); - // make sure the widget containing the added overlay is shown ... - m_PositionedOverlays[ pos ]->show(); // ... and reset the position of the widgets this->AdjustOverlayPosition(); } } void QmitkOverlayController::UpdateOverlayData( QmitkOverlay* overlay ) { overlay->GenerateData( m_PropertyList ); } void QmitkOverlayController::RemoveOverlay( QmitkOverlay* overlay ) { if ( overlay != NULL ) { // get desired position and layer of the overlay QmitkOverlay::DisplayPosition pos = overlay->GetPosition(); OverlayVector::iterator iter = std::find( m_AllOverlays.begin(), m_AllOverlays.end(), overlay ); if ( iter != m_AllOverlays.end() ) { m_AllOverlays.erase( iter ); overlay->GetWidget()->setParent( NULL ); overlay->GetWidget()->hide(); if ( m_PositionedOverlays[ pos ]->layout()->isEmpty() ) { m_PositionedOverlays[ pos ]->hide(); } else { this->RestackOverlays( pos ); // reset the position of the widgets this->AdjustOverlayPosition(); } } overlay->deleteLater(); } } void QmitkOverlayController::AlignOverlays() { //OverlayVector::iterator overlayIter; //for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ ) //{ // int stackLayer = dynamic_cast( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->isEmpty() ? 0 : layer; // dynamic_cast( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->addWidget( (*overlayIter)->GetWidget(), stackLayer, Qt::AlignLeft ); //} } void QmitkOverlayController::RestackOverlays( QmitkOverlay::DisplayPosition pos ) { OverlayVector::iterator overlayIter; QBoxLayout* layout = dynamic_cast( m_PositionedOverlays[ pos ]->layout() ); std::sort( m_AllOverlays.begin(), m_AllOverlays.end() ); for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ ) { // do nothing if the overlay is not in the right position if ( (*overlayIter)->GetPosition() != pos ) { continue; } // determine the desired stacking layer // if the overlay-container is empty, simply append the overlay to the list // if it's not empty, use the layer of the overlay unsigned int layer = (*overlayIter)->GetLayer(); int stackLayer = 0; if ( !layout->isEmpty() ) { stackLayer = layer; } switch ( pos ) { // same alignment for all lefts, ... case QmitkOverlay::top_Left : {} case QmitkOverlay::middle_Left : {} case QmitkOverlay::bottom_Left : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignLeft ); break; } // ... for all centers, ... case QmitkOverlay::top_Center : {} case QmitkOverlay::bottom_Center : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignCenter ); break; } // ... and for all rights case QmitkOverlay::top_Right : {} case QmitkOverlay::middle_Right : {} case QmitkOverlay::bottom_Right : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignRight ); break; } } } } void QmitkOverlayController::UpdateAllOverlays() { foreach( QmitkOverlay* overlay, m_AllOverlays ) { this->UpdateOverlayData( overlay ); } } \ No newline at end of file diff --git a/Modules/Overlays/files.cmake b/Modules/Overlays/files.cmake index 1d3b3feef8..6ef55033a8 100644 --- a/Modules/Overlays/files.cmake +++ b/Modules/Overlays/files.cmake @@ -1,14 +1,16 @@ -set(CPP_FILES +SET(CPP_FILES + QmitkCustomWidgetOverlay.cpp QmitkOverlay.cpp QmitkOverlayController.cpp QmitkScalarBar.cpp QmitkScalarBarOverlay.cpp QmitkTextOverlay.cpp ) -set(MOC_H_FILES + +SET(MOC_H_FILES QmitkOverlay.h QmitkOverlayController.h QmitkScalarBar.h QmitkScalarBarOverlay.h ) \ No newline at end of file diff --git a/Modules/PlanarFigure/DataManagement/mitkPlanarFigureControlPointStyleProperty.cpp b/Modules/PlanarFigure/DataManagement/mitkPlanarFigureControlPointStyleProperty.cpp index 67bd801fb6..3346c546a3 100644 --- a/Modules/PlanarFigure/DataManagement/mitkPlanarFigureControlPointStyleProperty.cpp +++ b/Modules/PlanarFigure/DataManagement/mitkPlanarFigureControlPointStyleProperty.cpp @@ -1,60 +1,75 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPlanarFigureControlPointStyleProperty.h" mitk::PlanarFigureControlPointStyleProperty::PlanarFigureControlPointStyleProperty( ) { this->AddEnumTypes(); this->SetValue( static_cast ( Square ) ); } mitk::PlanarFigureControlPointStyleProperty::PlanarFigureControlPointStyleProperty( const IdType &value ) { this->AddEnumTypes(); if ( this->IsValidEnumerationValue( value ) ) { this->SetValue( value ) ; } else { this->SetValue( static_cast ( Square ) ); } } mitk::PlanarFigureControlPointStyleProperty::PlanarFigureControlPointStyleProperty( const std::string &value ) { this->AddEnumTypes(); if ( this->IsValidEnumerationValue( value ) ) { this->SetValue( value ); } else { this->SetValue( static_cast( Square ) ); } } void mitk::PlanarFigureControlPointStyleProperty::AddEnumTypes() { this->AddEnum( "Square", static_cast( Square ) ); this->AddEnum( "Circle", static_cast( Circle ) ); } bool mitk::PlanarFigureControlPointStyleProperty::AddEnum( const std::string& name, const IdType& id ) { return Superclass::AddEnum( name, id ); } mitk::PlanarFigureControlPointStyleProperty::Shape mitk::PlanarFigureControlPointStyleProperty::GetShape() { return static_cast( this->GetValueAsId() ); } void mitk::PlanarFigureControlPointStyleProperty::SetShape(mitk::PlanarFigureControlPointStyleProperty::Shape shape) { this->SetValue( static_cast( shape ) ); } diff --git a/Modules/Qmitk/QmitkProgressBar.cpp b/Modules/Qmitk/QmitkProgressBar.cpp index 8abc70849d..df320ceab7 100644 --- a/Modules/Qmitk/QmitkProgressBar.cpp +++ b/Modules/Qmitk/QmitkProgressBar.cpp @@ -1,123 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkProgressBar.h" #include "mitkProgressBar.h" #include "mitkRenderingManager.h" #include #include /** * Reset the progress bar. The progress bar "rewinds" and shows no progress. */ void QmitkProgressBar::Reset() { this->reset(); this->hide(); m_TotalSteps = 0; m_Progress = 0; } /** * Sets whether the current progress value is displayed. */ void QmitkProgressBar::SetPercentageVisible(bool visible) { emit SignalSetPercentageVisible(visible); } /** *Documentation *@brief Adds steps to totalSteps. */ void QmitkProgressBar::AddStepsToDo(unsigned int steps) { emit SignalAddStepsToDo(steps); } /** * Documentation * @brief Sets the current amount of progress to current progress + steps. * @param steps the number of steps done since last Progress(int steps) call. */ void QmitkProgressBar::Progress(unsigned int steps) { emit SignalProgress(steps); } QmitkProgressBar::QmitkProgressBar(QWidget * parent, const char * /*name*/) :QProgressBar(parent), ProgressBarImplementation() { m_TotalSteps = 0; m_Progress = 0; this->hide(); this->SetPercentageVisible(true); connect( this, SIGNAL(SignalAddStepsToDo(unsigned int)), this, SLOT(SlotAddStepsToDo(unsigned int)) ); connect( this, SIGNAL(SignalProgress(unsigned int)), this, SLOT(SlotProgress(unsigned int)) ); connect( this, SIGNAL(SignalSetPercentageVisible(bool)), this, SLOT(SlotSetPercentageVisible(bool)) ); mitk::ProgressBar::GetInstance()->RegisterImplementationInstance(this); } QmitkProgressBar::~QmitkProgressBar() { mitk::ProgressBar::GetInstance()->UnregisterImplementationInstance(this); } void QmitkProgressBar::SlotProgress(unsigned int steps) { m_Progress += steps; this->setValue(m_Progress); if (m_Progress >= m_TotalSteps) Reset(); else { this->show(); } // Update views if repaint has been requested in the meanwhile // (because Qt event loop is not reached while progress bar is updating, // unless the application is threaded) + qApp->processEvents(); mitk::RenderingManager::GetInstance()->ExecutePendingRequests(); } void QmitkProgressBar::SlotAddStepsToDo(unsigned int steps) { m_TotalSteps += steps; this->setMaximum(m_TotalSteps); this->setValue(m_Progress); if (m_TotalSteps > 0) { this->show(); } // Update views if repaint has been requested in the meanwhile // (because Qt event loop is not reached while progress bar is updating, // unless the application is threaded) mitk::RenderingManager::GetInstance()->ExecutePendingRequests(); } void QmitkProgressBar::SlotSetPercentageVisible(bool visible) { this->setTextVisible(visible); } diff --git a/Modules/QmitkExt/QmitkClosingToolGUI.cpp b/Modules/QmitkExt/QmitkClosingToolGUI.cpp index cbc1830fe6..98f6da4ce1 100644 --- a/Modules/QmitkExt/QmitkClosingToolGUI.cpp +++ b/Modules/QmitkExt/QmitkClosingToolGUI.cpp @@ -1,13 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkClosingToolGUI.h" MITK_TOOL_GUI_MACRO( , QmitkClosingToolGUI, "") QmitkClosingToolGUI::QmitkClosingToolGUI() { } QmitkClosingToolGUI::~QmitkClosingToolGUI() { } \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkClosingToolGUI.h b/Modules/QmitkExt/QmitkClosingToolGUI.h index 25f5858545..855708bf54 100644 --- a/Modules/QmitkExt/QmitkClosingToolGUI.h +++ b/Modules/QmitkExt/QmitkClosingToolGUI.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKCLOSINGTOOLGUI_H #define QMITKCLOSINGTOOLGUI_H #include "QmitkMorphologicToolGUI.h" #include "QmitkExtExports.h" class /*QmitkExt_EXPORTS*/ QmitkClosingToolGUI : public QmitkMorphologicToolGUI { Q_OBJECT public: mitkClassMacro(QmitkClosingToolGUI, QmitkMorphologicToolGUI); itkNewMacro(QmitkClosingToolGUI); protected: virtual ~QmitkClosingToolGUI(); QmitkClosingToolGUI(); }; #endif \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.cpp b/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.cpp index 4675cd75f4..73b483e9b8 100644 --- a/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.cpp +++ b/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.cpp @@ -1,187 +1,202 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkCorrespondingPointSetsWidget.h" #include #include #include #include QmitkCorrespondingPointSetsWidget::QmitkCorrespondingPointSetsWidget(QWidget *parent): QWidget(parent), m_CorrespondingPointSetsView(NULL) { // create new QTableView m_CorrespondingPointSetsView = new QmitkCorrespondingPointSetsView(); // setup user interface SetupUi(); // setup connections connect( this->m_CorrespondingPointSetsView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged()) ); connect( this->m_CorrespondingPointSetsView, SIGNAL(SignalAddPointsModeChanged(bool)), this, SLOT(OnAddPointsModeChanged(bool)) ); } QmitkCorrespondingPointSetsWidget::~QmitkCorrespondingPointSetsWidget() { delete m_CorrespondingPointSetsView; } void QmitkCorrespondingPointSetsWidget::SetupUi() { QBoxLayout* lay1 = new QVBoxLayout(this); // add status bar buttons if (QTPropShowButtonBar) { bool isPointSelected = this->m_CorrespondingPointSetsView->IsPointSelected(); QBoxLayout* lay2 = new QHBoxLayout(); lay1->addLayout(lay2); lay2->stretch(true); QStatusBar* statusBar = new QStatusBar(this); statusBar->setMaximumHeight(25); m_CreatePointSetBtn = new QToolButton(); m_CreatePointSetBtn->setAutoRaise(true); m_CreatePointSetBtn->setIcon(QIcon(":/qmitk/btnAddPointSet.png")); m_CreatePointSetBtn->setToolTip(QString("Create new point set")); connect(this->m_CreatePointSetBtn, SIGNAL(clicked()), this, SLOT(AddPointSet())); statusBar->addWidget(m_CreatePointSetBtn); m_AddPointsBtn = new QToolButton(); m_AddPointsBtn->setAutoRaise(true); m_AddPointsBtn->setIcon(QIcon(":/qmitk/btnSetPoints.png")); m_AddPointsBtn->setToolTip(QString("Check to add new points (shift-click)")); m_AddPointsBtn->setCheckable(true); connect(this->m_AddPointsBtn, SIGNAL(clicked(bool)), this, SLOT(AddPointsMode(bool))); statusBar->addWidget(m_AddPointsBtn); m_MovePointUpBtn = new QToolButton(); m_MovePointUpBtn->setAutoRaise(true); m_MovePointUpBtn->setIcon(QIcon(":/qmitk/btnMoveUp.png")); m_MovePointUpBtn->setToolTip(QString("Move selected point up")); connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp())); statusBar->addWidget(m_MovePointUpBtn); m_MovePointDownBtn = new QToolButton(); m_MovePointDownBtn->setAutoRaise(true); m_MovePointDownBtn->setIcon(QIcon(":/qmitk/btnMoveDown.png")); m_MovePointDownBtn->setToolTip(QString("Move selected point down")); connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown())); statusBar->addWidget(m_MovePointDownBtn); m_RemovePointBtn = new QToolButton(); m_RemovePointBtn->setAutoRaise(true); m_RemovePointBtn->setIcon(QIcon(":/qmitk/btnRemovePoint.png")); m_RemovePointBtn->setToolTip(QString("Remove selected point")); connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint())); statusBar->addWidget(m_RemovePointBtn); m_SwapSetsBtn = new QToolButton(); m_SwapSetsBtn->setAutoRaise(true); m_SwapSetsBtn->setIcon(QIcon(":/qmitk/btnSwapSets.png")); m_SwapSetsBtn->setToolTip(QString("Swap the two selected point sets")); m_SwapSetsBtn->setCheckable(true); connect(this->m_SwapSetsBtn, SIGNAL(clicked(bool)), this, SLOT(SwapPointSets(bool))); statusBar->addWidget(m_SwapSetsBtn); // disable buttons m_MovePointUpBtn->setEnabled(false); m_MovePointDownBtn->setEnabled(false); m_RemovePointBtn->setEnabled(false); m_SwapSetsBtn->setEnabled(false); m_AddPointsBtn->setEnabled(false); lay2->addWidget(statusBar); } lay1->insertWidget(0,m_CorrespondingPointSetsView); this->setLayout(lay1); } void QmitkCorrespondingPointSetsWidget::SetPointSetNodes(std::vector nodes) { this->m_CorrespondingPointSetsView->SetPointSetNodes(nodes); if (this->GetPointSetNodes().size()<2) m_SwapSetsBtn->setEnabled(false); else m_SwapSetsBtn->setEnabled(true); } std::vector QmitkCorrespondingPointSetsWidget::GetPointSetNodes() { return this->m_CorrespondingPointSetsView->GetPointSetNodes(); } void QmitkCorrespondingPointSetsWidget::SetMultiWidget(QmitkStdMultiWidget* multiWidget) { m_CorrespondingPointSetsView->SetMultiWidget(multiWidget); } void QmitkCorrespondingPointSetsWidget::SetDataStorage(mitk::DataStorage::Pointer dataStorage) { m_CorrespondingPointSetsView->SetDataStorage(dataStorage); } void QmitkCorrespondingPointSetsWidget::UpdateSelection(mitk::DataNode* selectedNode) { m_AddPointsBtn->setEnabled(false); if (!selectedNode || !(dynamic_cast(selectedNode->GetData()))) return; bool visible = false; selectedNode->GetPropertyValue("visible", visible); if (visible){ m_AddPointsBtn->setEnabled(true); m_CorrespondingPointSetsView->UpdateSelection(selectedNode); } } bool QmitkCorrespondingPointSetsWidget::QTPropButtonBarEnabled() const { return this->QTPropShowButtonBar; } void QmitkCorrespondingPointSetsWidget::QTPropSetButtonBarEnabled(bool showBB) { this->QTPropShowButtonBar = showBB; } void QmitkCorrespondingPointSetsWidget::AddPointSet() { m_CorrespondingPointSetsView->AddPointSet(); } void QmitkCorrespondingPointSetsWidget::OnPointSelectionChanged() { if ( this->m_CorrespondingPointSetsView->IsPointSelected() ) { m_MovePointUpBtn->setEnabled(true); m_MovePointDownBtn->setEnabled(true); m_RemovePointBtn->setEnabled(true); } else { m_MovePointUpBtn->setEnabled(false); m_MovePointDownBtn->setEnabled(false); m_RemovePointBtn->setEnabled(false); } } void QmitkCorrespondingPointSetsWidget::RemoveSelectedPoint() { this->m_CorrespondingPointSetsView->RemoveSelectedPoint(); } void QmitkCorrespondingPointSetsWidget::MoveSelectedPointDown() { this->m_CorrespondingPointSetsView->MoveSelectedPointDown(); } void QmitkCorrespondingPointSetsWidget::MoveSelectedPointUp() { this->m_CorrespondingPointSetsView->MoveSelectedPointUp(); } void QmitkCorrespondingPointSetsWidget::AddPointsMode(bool checked) { this->m_CorrespondingPointSetsView->AddPointsMode(checked); } void QmitkCorrespondingPointSetsWidget::OnAddPointsModeChanged(bool enabled) { this->m_AddPointsBtn->setChecked(enabled); } void QmitkCorrespondingPointSetsWidget::SwapPointSets(bool checked) { this->m_CorrespondingPointSetsView->SwapPointSets(checked); } diff --git a/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.h b/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.h index a4bededa07..01c27b0b7c 100644 --- a/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.h +++ b/Modules/QmitkExt/QmitkCorrespondingPointSetsWidget.h @@ -1,117 +1,132 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QmitkCorrespondingPointSetsWidget_H #define QmitkCorrespondingPointSetsWidget_H #include #include #include "QmitkExtExports.h" #include #include #include #include #include #include /*! * \brief Widget for regular operations on two point sets * * Displays two sets of point coordinates, buttons and a context menu to enable modifications to the point sets * * \li creation of new point sets * \li adding/removing points * \li move points * \li clear all points from a set * \li clear all points in one time step of one set * * The user/application module of this widget needs to * assign two visible point sets to the widget * (via SetPointSetNodes(std::vector nodes)), * preferrably by passing all visible data nodes contained * in the data storage to the widget every time * DataStorageChanged() is called. * * The user/application module of this widget needs to * assign one selected point set to the widget * (via UpdateSelection(mitk::DataNode* selectedNode)), * preferrably by passing the selected data node contained * in the data storage to the widget every time * OnSelectionChanged() is called. * * The user/application module of this widget needs to * assign a QmitkStdMultiWidget and a mitk::DataStorage * to the widget (via SetMultiWidget and SetDataStorage). */ class QmitkExt_EXPORT QmitkCorrespondingPointSetsWidget : public QWidget { Q_OBJECT Q_PROPERTY(bool QTPropShowButtonBar READ QTPropButtonBarEnabled WRITE QTPropSetButtonBarEnabled) public: QmitkCorrespondingPointSetsWidget(QWidget *parent = 0); ~QmitkCorrespondingPointSetsWidget(); /// calls SetPointSetNodes of the according QmitkCorrespondingPointSetsView void SetPointSetNodes(std::vector nodes); /// returns the point set nodes contained in the table model /// calls GetPointSetNodes of the according QmitkCorrespondingPointSetsView std::vector GetPointSetNodes(); /// calls SetMultiWidget of the according QmitkCorrespondingPointSetsView void SetMultiWidget(QmitkStdMultiWidget* multiWidget); /// calls SetDataStorage of the according QmitkCorrespondingPointSetsView void SetDataStorage(mitk::DataStorage::Pointer dataStorage); /// calls UpdateSelection of the according QmitkCorrespondingPointSetsView void UpdateSelection(mitk::DataNode* selectedNode); /// returns the qt property which indicates an activated/deactivated button bar below the table bool QTPropButtonBarEnabled() const; /// sets the qt property which activates/deactivates the button bar below the table void QTPropSetButtonBarEnabled(bool showBB); signals: protected slots: /// enables/disables buttons if a/no point is selected void OnPointSelectionChanged(); /// add new point set to data manager void AddPointSet(); /// enable if new points should be a added void AddPointsMode(bool checked); void RemoveSelectedPoint(); void MoveSelectedPointDown(); void MoveSelectedPointUp(); /// toggles m_AddPointsBtn checked state void OnAddPointsModeChanged(bool enabled); /// swap the two table columns columns void SwapPointSets(bool checked); protected: void SetupUi(); bool QTPropShowButtonBar; QmitkCorrespondingPointSetsView* m_CorrespondingPointSetsView; QToolButton* m_CreatePointSetBtn; QToolButton* m_MovePointUpBtn; QToolButton* m_MovePointDownBtn; QToolButton* m_RemovePointBtn; QToolButton* m_AddPointsBtn; QToolButton* m_SwapSetsBtn; }; #endif diff --git a/Modules/QmitkExt/QmitkDilateToolGUI.cpp b/Modules/QmitkExt/QmitkDilateToolGUI.cpp index 17facad0b9..2e6a46f784 100644 --- a/Modules/QmitkExt/QmitkDilateToolGUI.cpp +++ b/Modules/QmitkExt/QmitkDilateToolGUI.cpp @@ -1,11 +1,26 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkDilateToolGUI.h" MITK_TOOL_GUI_MACRO( , QmitkDilateToolGUI, "") QmitkDilateToolGUI::QmitkDilateToolGUI() { } QmitkDilateToolGUI::~QmitkDilateToolGUI() { } diff --git a/Modules/QmitkExt/QmitkDilateToolGUI.h b/Modules/QmitkExt/QmitkDilateToolGUI.h index 8ab401e6f9..c76085f1a3 100644 --- a/Modules/QmitkExt/QmitkDilateToolGUI.h +++ b/Modules/QmitkExt/QmitkDilateToolGUI.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKDILATETOOLGUI_H #define QMITKDILATETOOLGUI_H #include "QmitkMorphologicToolGUI.h" #include "QmitkExtExports.h" class /*QmitkExt_EXPORTS*/ QmitkDilateToolGUI : public QmitkMorphologicToolGUI { Q_OBJECT public: mitkClassMacro(QmitkDilateToolGUI, QmitkMorphologicToolGUI); itkNewMacro(QmitkDilateToolGUI); protected: virtual ~QmitkDilateToolGUI(); QmitkDilateToolGUI(); }; #endif \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkErodeToolGUI.cpp b/Modules/QmitkExt/QmitkErodeToolGUI.cpp index 28c3810720..4a0685378b 100644 --- a/Modules/QmitkExt/QmitkErodeToolGUI.cpp +++ b/Modules/QmitkExt/QmitkErodeToolGUI.cpp @@ -1,13 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkErodeToolGUI.h" MITK_TOOL_GUI_MACRO( , QmitkErodeToolGUI, "") QmitkErodeToolGUI::QmitkErodeToolGUI() { } QmitkErodeToolGUI::~QmitkErodeToolGUI() { } \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkErodeToolGUI.h b/Modules/QmitkExt/QmitkErodeToolGUI.h index 8cf8d12fac..5811166594 100644 --- a/Modules/QmitkExt/QmitkErodeToolGUI.h +++ b/Modules/QmitkExt/QmitkErodeToolGUI.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKERODETOOLGUI_H #define QMITKERODETOOLGUI_H #include "QmitkMorphologicToolGUI.h" #include "QmitkExtExports.h" class /*QmitkExt_EXPORTS*/ QmitkErodeToolGUI : public QmitkMorphologicToolGUI { Q_OBJECT public: mitkClassMacro(QmitkErodeToolGUI, QmitkMorphologicToolGUI); itkNewMacro(QmitkErodeToolGUI); protected: virtual ~QmitkErodeToolGUI(); QmitkErodeToolGUI(); }; #endif \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkOpeningToolGUI.cpp b/Modules/QmitkExt/QmitkOpeningToolGUI.cpp index 2de2abe901..8f46ade9d4 100644 --- a/Modules/QmitkExt/QmitkOpeningToolGUI.cpp +++ b/Modules/QmitkExt/QmitkOpeningToolGUI.cpp @@ -1,13 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkOpeningToolGUI.h" MITK_TOOL_GUI_MACRO( , QmitkOpeningToolGUI, "") QmitkOpeningToolGUI::QmitkOpeningToolGUI() { } QmitkOpeningToolGUI::~QmitkOpeningToolGUI() { } \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkOpeningToolGUI.h b/Modules/QmitkExt/QmitkOpeningToolGUI.h index a93c0468a7..98b04b96a9 100644 --- a/Modules/QmitkExt/QmitkOpeningToolGUI.h +++ b/Modules/QmitkExt/QmitkOpeningToolGUI.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKOPENINGTOOLGUI_H #define QMITKOPENINGTOOLGUI_H #include "QmitkMorphologicToolGUI.h" #include "QmitkExtExports.h" class /*QmitkExt_EXPORTS*/ QmitkOpeningToolGUI : public QmitkMorphologicToolGUI { Q_OBJECT public: mitkClassMacro(QmitkOpeningToolGUI, QmitkMorphologicToolGUI); itkNewMacro(QmitkOpeningToolGUI); protected: virtual ~QmitkOpeningToolGUI(); QmitkOpeningToolGUI(); }; #endif \ No newline at end of file diff --git a/Modules/QmitkExt/QmitkPointListWidget.cpp b/Modules/QmitkExt/QmitkPointListWidget.cpp index e594b84a17..b17f70855a 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.cpp +++ b/Modules/QmitkExt/QmitkPointListWidget.cpp @@ -1,440 +1,455 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkPointListWidget.h" #include #include #include #include #include #include #include #include #include "btnLoad.xpm" #include "btnSave.xpm" #include "btnClear.xpm" #include "btnSetPoints.xpm" #include "btnSetPointsManually.xpm" #include "btnUp.xpm" #include "btnDown.xpm" QmitkPointListWidget::QmitkPointListWidget(QWidget *parent, int orientation): QWidget(parent), m_PointListView(NULL), m_MultiWidget(NULL), m_PointSetNode(NULL), m_Orientation(0), m_MovePointUpBtn(NULL), m_MovePointDownBtn(NULL), m_RemovePointBtn(NULL), m_SavePointsBtn(NULL), m_LoadPointsBtn(NULL), m_ToggleAddPoint(NULL), m_AddPoint(NULL), m_Interactor(NULL), m_TimeStep(0), m_EditAllowed(true), m_NodeObserverTag(0) { m_PointListView = new QmitkPointListView(); if(orientation != 0) m_Orientation = orientation; SetupUi(); SetupConnections(); ObserveNewNode(NULL); } QmitkPointListWidget::~QmitkPointListWidget() { if (m_Interactor) mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; if(m_PointSetNode && m_NodeObserverTag) { m_PointSetNode->RemoveObserver(m_NodeObserverTag); m_NodeObserverTag = 0; } m_MultiWidget = NULL; delete m_PointListView; } void QmitkPointListWidget::SetupConnections() { //m_PointListView->setModel(m_PointListModel); connect(this->m_LoadPointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnLoadPoints())); connect(this->m_SavePointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnSavePoints())); connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp())); connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown())); connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint())); connect(this->m_ToggleAddPoint, SIGNAL(toggled(bool)), this, SLOT(OnBtnAddPoint(bool))); connect(this->m_AddPoint, SIGNAL(clicked()), this, SLOT(OnBtnAddPointManually())); connect(this->m_PointListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnListDoubleClick())); connect(this->m_PointListView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged())); } void QmitkPointListWidget::SetupUi() { //Setup the buttons m_ToggleAddPoint = new QPushButton();//iconSetPoints, "", this); m_ToggleAddPoint->setMaximumSize(25,25); m_ToggleAddPoint->setCheckable(true); m_ToggleAddPoint->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)"); QIcon iconAdd(btnSetPoints_xpm); m_ToggleAddPoint->setIcon(iconAdd); m_AddPoint = new QPushButton();//iconSetPoints, "", this); m_AddPoint->setMaximumSize(25,25); m_AddPoint->setToolTip("Manually add point"); QIcon iconAddManually(btnSetPointsManually_xpm); m_AddPoint->setIcon(iconAddManually); m_RemovePointBtn = new QPushButton(); m_RemovePointBtn->setMaximumSize(25, 25); const QIcon iconDel(btnClear_xpm); m_RemovePointBtn->setIcon(iconDel); m_RemovePointBtn->setToolTip("Erase one point from list (Hotkey: DEL)"); m_MovePointUpBtn = new QPushButton(); m_MovePointUpBtn->setMaximumSize(25, 25); const QIcon iconUp(btnUp_xpm); m_MovePointUpBtn->setIcon(iconUp); m_MovePointUpBtn->setToolTip("Swap selected point upwards (Hotkey: F2)"); m_MovePointDownBtn = new QPushButton(); m_MovePointDownBtn->setMaximumSize(25, 25); const QIcon iconDown(btnDown_xpm); m_MovePointDownBtn->setIcon(iconDown); m_MovePointDownBtn->setToolTip("Swap selected point downwards (Hotkey: F3)"); m_SavePointsBtn = new QPushButton(); m_SavePointsBtn->setMaximumSize(25, 25); QIcon iconSave(btnSave_xpm); m_SavePointsBtn->setIcon(iconSave); m_SavePointsBtn->setToolTip("Save points to file"); m_LoadPointsBtn = new QPushButton(); m_LoadPointsBtn->setMaximumSize(25, 25); QIcon iconLoad(btnLoad_xpm); m_LoadPointsBtn->setIcon(iconLoad); m_LoadPointsBtn->setToolTip("Load list of points from file (REPLACES current content)"); int i; QBoxLayout* lay1; QBoxLayout* lay2; switch (m_Orientation) { case 0: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i = 0; break; case 1: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=-1; break; case 2: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=0; break; default: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i=-1; break; } //setup Layouts this->setLayout(lay1); lay1->addLayout(lay2); lay2->stretch(true); lay2->addWidget(m_ToggleAddPoint); lay2->addWidget(m_AddPoint); lay2->addWidget(m_RemovePointBtn); lay2->addWidget(m_MovePointUpBtn); lay2->addWidget(m_MovePointDownBtn); lay2->addWidget(m_SavePointsBtn); lay2->addWidget(m_LoadPointsBtn); //lay2->addSpacing();; lay1->insertWidget(i,m_PointListView); this->setLayout(lay1); } void QmitkPointListWidget::SetPointSet(mitk::PointSet* newPs) { if(newPs == NULL) return; this->m_PointSetNode->SetData(newPs); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(m_PointSetNode); ObserveNewNode(m_PointSetNode); } void QmitkPointListWidget::SetPointSetNode(mitk::DataNode *newNode) { ObserveNewNode(newNode); if (newNode != NULL) dynamic_cast(this->m_PointListView->model())->SetPointSetNode(newNode); else dynamic_cast(this->m_PointListView->model())->SetPointSetNode(NULL); } void QmitkPointListWidget::OnBtnSavePoints() { if ((dynamic_cast(m_PointSetNode->GetData())) == NULL) return; // don't write empty point sets. If application logic requires something else then do something else. if ((dynamic_cast(m_PointSetNode->GetData()))->GetSize() == 0) return; // let the user choose a file std::string name(""); QString fileNameProposal = QString("/PointSet.mps");//.arg(m_PointSetNode->GetName().c_str()); //"PointSet.mps"; QString aFilename = QFileDialog::getSaveFileName( NULL, "Save point set", QDir::currentPath() + fileNameProposal, "MITK Pointset (*.mps)" ); if ( aFilename.isEmpty() ) return; try { // instantiate the writer and add the point-sets to write mitk::PointSetWriter::Pointer writer = mitk::PointSetWriter::New(); writer->SetInput( dynamic_cast(m_PointSetNode->GetData()) ); writer->SetFileName( aFilename.toLatin1() ); writer->Update(); } catch(...) { QMessageBox::warning( this, "Save point set", QString("File writer reported problems writing %1\n\n" "PLEASE CHECK output file!").arg(aFilename) ); } } void QmitkPointListWidget::OnBtnLoadPoints() { // get the name of the file to load QString filename = QFileDialog::getOpenFileName( NULL, "Open MITK Pointset", "", "MITK Point Sets (*.mps)"); if ( filename.isEmpty() ) return; // attempt to load file try { mitk::PointSetReader::Pointer reader = mitk::PointSetReader::New(); reader->SetFileName( filename.toLatin1() ); reader->Update(); mitk::PointSet::Pointer pointSet = reader->GetOutput(); if ( pointSet.IsNull() ) { QMessageBox::warning( this, "Load point set", QString("File reader could not read %1").arg(filename) ); return; } // loading successful // bool interactionOn( m_Interactor.IsNotNull() ); // if (interactionOn) // { // OnEditPointSetButtonToggled(false); // } // this->SetPointSet(pointSet); // if (interactionOn) // { // OnEditPointSetButtonToggled(true); // } } catch(...) { QMessageBox::warning( this, "Load point set", QString("File reader collapsed while reading %1").arg(filename) ); } emit PointListChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } mitk::PointSet* QmitkPointListWidget::GetPointSet() { return dynamic_cast(m_PointSetNode->GetData()); } mitk::DataNode* QmitkPointListWidget::GetPointSetNode() { return m_PointSetNode; } void QmitkPointListWidget::SetMultiWidget(QmitkStdMultiWidget *multiWidget) { this->m_MultiWidget = multiWidget; m_PointListView->SetMultiWidget(multiWidget); } void QmitkPointListWidget::RemoveSelectedPoint() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->RemoveSelectedPoint(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointDown() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointDown(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointUp() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointUp(); emit PointListChanged(); } void QmitkPointListWidget::OnBtnAddPoint(bool checked) { if (m_PointSetNode) { if (checked) { m_Interactor = dynamic_cast(m_PointSetNode->GetInteractor()); if (m_Interactor.IsNull())//if not present, instanciate one m_Interactor = mitk::PointSetInteractor::New("pointsetinteractor", m_PointSetNode); //add it to global interaction to activate it mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor ); } else if ( m_Interactor ) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; } emit EditPointSets(checked); mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget4->GetRenderWindow())->RequestUpdate(); } } void QmitkPointListWidget::OnBtnAddPointManually() { mitk::PointSet* pointSet = this->GetPointSet(); int currentPosition = pointSet->GetSize(); QmitkEditPointDialog editPointDialog(this); editPointDialog.SetPoint(pointSet, currentPosition, m_TimeStep); editPointDialog.exec(); } //void QmitkPointListWidget::SetMultiWidget(QmitkStdMultiWidget *multiWidget) //{ // this->m_MultiWidget = multiWidget; // this->m_PointListView->SetMultiWidget(multiWidget); //} void QmitkPointListWidget::OnListDoubleClick() { ; } void QmitkPointListWidget::OnPointSelectionChanged() { emit this->PointSelectionChanged(); } void QmitkPointListWidget::DeactivateInteractor(bool /*deactivate*/) { ; } void QmitkPointListWidget::EnableEditButton( bool enabled ) { m_EditAllowed = enabled; if (enabled == false) m_ToggleAddPoint->setEnabled(false); else m_ToggleAddPoint->setEnabled(true); OnBtnAddPoint(enabled); } void QmitkPointListWidget::ObserveNewNode( mitk::DataNode* node ) { // remove old observer if ( m_PointSetNode ) { if (m_Interactor) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; m_ToggleAddPoint->setChecked( false ); } m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; } m_PointSetNode = node; // add new observer if necessary if ( m_PointSetNode ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListWidget::OnNodeDeleted ); m_NodeObserverTag = m_PointSetNode->AddObserver( itk::DeleteEvent(), command ); } else { m_NodeObserverTag = 0; } if (m_EditAllowed == true) m_ToggleAddPoint->setEnabled( m_PointSetNode ); else m_ToggleAddPoint->setEnabled( false ); m_RemovePointBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); } void QmitkPointListWidget::OnNodeDeleted( const itk::EventObject & /*e*/ ) { if(m_PointSetNode.IsNotNull() && ! m_NodeObserverTag) m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; m_PointSetNode = NULL; m_PointListView->SetPointSetNode(NULL); m_ToggleAddPoint->setEnabled(false); m_RemovePointBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); } diff --git a/Modules/QmitkExt/QmitkPointListWidget.h b/Modules/QmitkExt/QmitkPointListWidget.h index 876e9d9556..a9b5924be5 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.h +++ b/Modules/QmitkExt/QmitkPointListWidget.h @@ -1,120 +1,135 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QmitkPointListWidget_H #define QmitkPointListWidget_H #include #include #include "QmitkExtExports.h" #include #include #include #include #include /*! * \brief Widget for regular operations on point sets * * Displays a list of point coordinates and a couple of * buttons which * * \li enable point set interaction * \li clear all points from a set * \li load points from file * \li save points to file * * The user/application module of this widget needs to * assign a mitk::PointSet object to this widget. The user * also has to decide whether it wants to put the point set * into (a) DataStorage. This widget will not add/remove * point sets to DataStorage. * * If the render window crosshair should be moved to the * currently selected point, the widget user has to provide * a QmitkStdMultiWidget object. */ class QmitkExt_EXPORT QmitkPointListWidget : public QWidget { Q_OBJECT public: QmitkPointListWidget(QWidget *parent = 0, int orientation = 0); ~QmitkPointListWidget(); void SetupConnections(); /// assign a point set (contained in a node of DataStorage) for observation void SetPointSet(mitk::PointSet* newPs); mitk::PointSet* GetPointSet(); /// assign a point set (contained in a node of DataStorage) for observation void SetPointSetNode(mitk::DataNode* newNode); mitk::DataNode* GetPointSetNode(); /// assign a QmitkStdMultiWidget for updating render window crosshair void SetMultiWidget(QmitkStdMultiWidget* multiWidget); /// itk observer for node "delete" events void OnNodeDeleted( const itk::EventObject & e ); public slots: void DeactivateInteractor(bool deactivate); void EnableEditButton(bool enabled); signals: /// signal to inform about the state of the EditPointSetButton, whether an interactor for setting points is active or not void EditPointSets(bool active); /// signal to inform that the selection of a point in the pointset has changed void PointSelectionChanged(); /// signal to inform about cleared or loaded point sets void PointListChanged(); protected slots: void OnBtnSavePoints(); void OnBtnLoadPoints(); void RemoveSelectedPoint(); void MoveSelectedPointDown(); void MoveSelectedPointUp(); void OnBtnAddPoint(bool checked); void OnBtnAddPointManually(); //void OnBtnSetPointsMode(bool checked); /*! \brief pass through signal from PointListView that point selection has changed */ void OnPointSelectionChanged(); void OnListDoubleClick(); protected: void SetupUi(); void ObserveNewNode(mitk::DataNode* node); QmitkPointListView* m_PointListView; QmitkStdMultiWidget* m_MultiWidget; mitk::DataNode::Pointer m_PointSetNode; int m_Orientation; QPushButton* m_MovePointUpBtn; QPushButton* m_MovePointDownBtn; QPushButton* m_RemovePointBtn; QPushButton* m_SavePointsBtn; QPushButton* m_LoadPointsBtn; QPushButton* m_ToggleAddPoint; QPushButton* m_AddPoint; mitk::PointSetInteractor::Pointer m_Interactor; int m_TimeStep; bool m_EditAllowed; unsigned long m_NodeObserverTag; }; #endif diff --git a/Modules/SceneSerialization/mitkSceneReaderV1.cpp b/Modules/SceneSerialization/mitkSceneReaderV1.cpp index feeb0c445a..1a9b31aa96 100644 --- a/Modules/SceneSerialization/mitkSceneReaderV1.cpp +++ b/Modules/SceneSerialization/mitkSceneReaderV1.cpp @@ -1,307 +1,320 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSceneReaderV1.h" #include "mitkSerializerMacros.h" #include "mitkDataNodeFactory.h" #include "mitkBaseRenderer.h" #include "mitkPropertyListDeserializer.h" +#include "mitkProgressBar.h" #include "Poco/Path.h" MITK_REGISTER_SERIALIZER(SceneReaderV1) bool mitk::SceneReaderV1::LoadScene( TiXmlDocument& document, const std::string& workingDirectory, DataStorage* storage ) { assert(storage); bool error(false); // TODO prepare to detect errors (such as cycles) from wrongly written or edited xml files + //Get number of elements to initialze progress bar + unsigned int listSize = 0; + for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node") ) + { + ++listSize; + } + + ProgressBar::GetInstance()->AddStepsToDo( listSize ); + // iterate all nodes // first level nodes should be elements for( TiXmlElement* element = document.FirstChildElement("node"); element != NULL; element = element->NextSiblingElement("node") ) { // 1. if there is a element, // - construct a name for the appropriate serializer // - try to instantiate this serializer via itk object factory // - if serializer could be created, use it to read the file into a BaseData object // - if successful, call the new node's SetData(..) DataNode::Pointer node = LoadBaseDataFromDataTag( element->FirstChildElement("data"), workingDirectory, error ); // create a node for the tag "data" and test if node was created // in case dataXmlElement is valid test whether it containts the "properties" child tag // and process further if and only if yes TiXmlElement *dataXmlElement = element->FirstChildElement("data"); if( dataXmlElement && dataXmlElement->FirstChildElement("properties") ) { TiXmlElement *baseDataElement = dataXmlElement->FirstChildElement("properties"); DecorateBaseDataWithProperties( node->GetData(), baseDataElement, workingDirectory); } // 2. check child nodes const char* uida = element->Attribute("UID"); std::string uid(""); if (uida) { uid = uida; m_NodeForID[uid] = node.GetPointer(); m_IDForNode[ node.GetPointer() ] = uid; } else { MITK_ERROR << "No UID found for current node. Node will have no parents."; error = true; } // remember node for later adding to DataStorage m_Nodes.insert( std::make_pair( node, std::list() ) ); // 3. if there are elements, remember parent objects for( TiXmlElement* source = element->FirstChildElement("source"); source != NULL; source = source->NextSiblingElement("source") ) { const char* sourceUID = source->Attribute("UID"); if (sourceUID) { m_Nodes[node].push_back( std::string(sourceUID) ); } } // 5. if there are nodes, // - instantiate the appropriate PropertyListDeSerializer // - use them to construct PropertyList objects // - add these properties to the node (if necessary, use renderwindow name) bool success = DecorateNodeWithProperties(node, element, workingDirectory); if (!success) { MITK_ERROR << "Could not load properties for node."; error = true; } + + ProgressBar::GetInstance()->Progress(); + } // end for all // remove all unknown parent UIDs for (NodesAndParentsMapType::iterator nodesIter = m_Nodes.begin(); nodesIter != m_Nodes.end(); ++nodesIter) { for (std::list::iterator parentsIter = nodesIter->second.begin(); parentsIter != nodesIter->second.end();) { if (m_NodeForID.find( *parentsIter ) == m_NodeForID.end()) { parentsIter = nodesIter->second.erase( parentsIter ); MITK_WARN << "Found a DataNode with unknown parents. Will add it to DataStorage without any parent objects."; error = true; } else { ++parentsIter; } } } // repeat // for all created nodes unsigned int lastMapSize(0); while ( lastMapSize != m_Nodes.size()) // this is to prevent infinite loops; each iteration must at least add one node to DataStorage { lastMapSize = m_Nodes.size(); for (NodesAndParentsMapType::iterator nodesIter = m_Nodes.begin(); nodesIter != m_Nodes.end(); ++nodesIter) { bool addNow(true); // if any parent node is not yet in DataStorage, skip node for now and check later for (std::list::iterator parentsIter = nodesIter->second.begin(); parentsIter != nodesIter->second.end(); ++parentsIter) { if ( !storage->Exists( m_NodeForID[ *parentsIter ] ) ) { addNow = false; break; } } if (addNow) { DataStorage::SetOfObjects::Pointer parents = DataStorage::SetOfObjects::New(); for (std::list::iterator parentsIter = nodesIter->second.begin(); parentsIter != nodesIter->second.end(); ++parentsIter) { parents->push_back( m_NodeForID[ *parentsIter ] ); } // if all parents are found in datastorage (or are unknown), add node to DataStorage storage->Add( nodesIter->first, parents ); // remove this node from m_Nodes m_Nodes.erase( nodesIter ); // break this for loop because iterators are probably invalid break; } } } // All nodes that are still in m_Nodes at this point are not part of a proper directed graph structure. We'll add such nodes without any parent information. for (NodesAndParentsMapType::iterator nodesIter = m_Nodes.begin(); nodesIter != m_Nodes.end(); ++nodesIter) { storage->Add( nodesIter->first ); MITK_WARN << "Encountered node that is not part of a directed graph structure. Will be added to DataStorage without parents."; error = true; } return !error; } mitk::DataNode::Pointer mitk::SceneReaderV1::LoadBaseDataFromDataTag( TiXmlElement* dataElement, const std::string& workingDirectory, bool& error ) { DataNode::Pointer node; if (dataElement) { const char* filename( dataElement->Attribute("file") ); if ( filename ) { DataNodeFactory::Pointer factory = DataNodeFactory::New(); factory->SetFileName( workingDirectory + Poco::Path::separator() + filename ); try { factory->Update(); node = factory->GetOutput(); } catch (std::exception& e) { MITK_ERROR << "Error during attempt to read '" << filename << "'. Exception says: " << e.what(); error = true; } if (node.IsNull()) { MITK_ERROR << "Error during attempt to read '" << filename << "'. Factory returned NULL object."; error = true; } } } // in case there was no element we create a new empty node (for appending a propertylist later) if (node.IsNull()) { node = DataNode::New(); } return node; } bool mitk::SceneReaderV1::DecorateNodeWithProperties(DataNode* node, TiXmlElement* nodeElement, const std::string& workingDirectory) { assert(node); assert(nodeElement); bool error(false); for( TiXmlElement* properties = nodeElement->FirstChildElement("properties"); properties != NULL; properties = properties->NextSiblingElement("properties") ) { const char* propertiesfilea( properties->Attribute("file") ); std::string propertiesfile( propertiesfilea ? propertiesfilea : "" ); const char* renderwindowa( properties->Attribute("renderwindow") ); std::string renderwindow( renderwindowa ? renderwindowa : "" ); BaseRenderer* renderer = BaseRenderer::GetByName( renderwindow ); if (renderer || renderwindow.empty()) { PropertyList::Pointer propertyList = node->GetPropertyList(renderer); // DataNode implementation always returns a propertylist // clear all properties from node that might be set by DataNodeFactory during loading propertyList->Clear(); // use deserializer to construct new properties PropertyListDeserializer::Pointer deserializer = PropertyListDeserializer::New(); deserializer->SetFilename(workingDirectory + Poco::Path::separator() + propertiesfile); bool success = deserializer->Deserialize(); error |= !success; PropertyList::Pointer readProperties = deserializer->GetOutput(); if (readProperties.IsNotNull()) { propertyList->ConcatenatePropertyList( readProperties, true ); // true = replace } else { MITK_ERROR << "Property list reader did not return a property list. This is an implementation error. Please tell your developer."; error = true; } } else { MITK_ERROR << "Found properties for renderer " << renderwindow << " but there is no such renderer in current application. Ignoring those properties"; error = true; } } return !error; } bool mitk::SceneReaderV1::DecorateBaseDataWithProperties(BaseData::Pointer data, TiXmlElement *baseDataNodeElem, const std::string &workingDir) { // check given variables, initialize error variable assert(baseDataNodeElem); bool error(false); // get the file name stored in the tag const char* baseDataPropertyFile( baseDataNodeElem->Attribute("file") ); // check if the filename was found if(baseDataPropertyFile) { //PropertyList::Pointer dataPropList = data->GetPropertyList(); PropertyListDeserializer::Pointer propertyDeserializer = PropertyListDeserializer::New(); // initialize the property reader propertyDeserializer->SetFilename(workingDir + Poco::Path::separator() + baseDataPropertyFile); bool ioSuccess = propertyDeserializer->Deserialize(); error = !ioSuccess; // get the output PropertyList::Pointer inProperties = propertyDeserializer->GetOutput(); // store the read-in properties to the given node or throw error otherwise if( inProperties.IsNotNull() ) { data->SetPropertyList( inProperties ); } else { MITK_ERROR << "The property deserializer did not return a (valid) property list."; error = true; } } else { MITK_ERROR << "Function DecorateBaseDataWithProperties(...) called with false TiXmlElement. \n \t ->Given element does not contain a 'file' attribute. \n"; error = true; } return !error; } diff --git a/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.h b/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.h index 47220c9dc5..630543888c 100644 --- a/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.h +++ b/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.h @@ -1,252 +1,267 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkAdaptiveThresholdIterator_h #define __itkAdaptiveThresholdIterator_h #include "itkIndex.h" #include "itkSize.h" #include "itkConditionalConstIterator.h" #include "itkImage.h" #include #include #include #include namespace itk { /** * \class AdaptiveThresholdIterator * \brief Iterates over an image using a variable image function, * which threshold can be varied during the iteration process. * * \ingroup ImageIterators * */ template class ITK_EXPORT AdaptiveThresholdIterator: public ConditionalConstIterator { public: /** Standard class typedefs. */ typedef AdaptiveThresholdIterator Self; typedef ConditionalConstIterator Superclass; typedef TImage ImageType; // A temporary image used for storing info about all indices typedef TImage TTempImage; typename TTempImage::Pointer tempPtr; //[!] isn't really used?! /** Type of function */ typedef TFunction FunctionType; /** Type of vector used to store location info in the spatial function */ typedef typename TFunction::InputType FunctionInputType; /** Size typedef support. */ typedef typename TImage::SizeType SizeType; /** Region typedef support */ typedef typename TImage::RegionType RegionType; typedef typename TImage::IndexType IndexType; /** Internal Pixel Type */ typedef typename TImage::InternalPixelType InternalPixelType; /** External Pixel Type */ typedef typename TImage::PixelType PixelType; /** Queue containing indices representing a voxel position */ typedef std::queue IndexQueueType; /** Map used to generate the output result */ typedef std::map QueueMapType; /** Dimension of the image the iterator walks. This constant is needed so * that functions that are templated over image iterator type (as opposed to * being templated over pixel type and dimension) can have compile time * access to the dimension of the image that the iterator walks. */ itkStaticConstMacro(NDimensions, unsigned int, TImage::ImageDimension); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor uses * an explicit seed pixel for the flood fill, the "startIndex" */ AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr, IndexType startIndex); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor uses * an explicit list of seed pixels for the flood fill, the "startIndex" */ AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr, std::vector & startIndex); /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. This version of the constructor * should be used when the seed pixel is unknown */ AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr); /** Default Destructor. */ virtual ~AdaptiveThresholdIterator() {}; /** Initializes the iterator, called from constructor */ void InitializeIterator(); //makes the iterator go one step further void DoExtendedFloodStep(); //set-method for member-variable void SetExpansionDirection(bool upwards); //Init-method void InitRegionGrowingState(); void SetMinTH(int min); void SetMaxTH(int max); int GetSeedPointValue(void); /** switch between fine and raw leakage detection */ void SetFineDetectionMode(bool fine = false) {m_FineDetectionMode = fine; m_DetectionStop = false;} /** Get the index. This provides a read only reference to the index. * This causes the index to be calculated from pointer arithmetic and is * therefore an expensive operation. * \sa SetIndex */ const IndexType GetIndex() { return (* m_QueueMap.find(m_RegionGrowingState)).second.front();}// [!] is never called?! const PixelType & Get(void) const { return const_cast(this->m_Image.GetPointer())->GetPixel((* m_QueueMap.find(m_RegionGrowingState)).second.front() ); } //[!] is never called?! void Set( const PixelType & value) { const_cast(this->m_Image.GetPointer())->GetPixel((* m_QueueMap.find(m_RegionGrowingState)).second.front() ) = value; } void GoToBegin(); /** Is the iterator at the end of the region? */ bool IsAtEnd() { return this->m_IsAtEnd; }; /** Walk forward one index */ void operator++() { this->DoExtendedFloodStep(); } virtual SmartPointer GetFunction() const { return m_Function; } /** operator= is provided to make sure the handle to the image is properly * reference counted. */ Self &operator=(const Self& it) { this->m_Image = it.m_Image; // copy the smart pointer this->m_Region = it.m_Region; return *this; } /** Compute whether the index of interest should be included in the flood */ bool IsPixelIncluded(const IndexType & index) const; //Calculate the value the outputImage is initialized to static int CalculateInitializeValue(int lower, int upper) { return ((upper - lower)+1)*(-1); }; int GetLeakagePoint(void) {return m_DetectedLeakagePoint;} protected: /* * @brief Pointer on the output image to which the result shall be written */ SmartPointer m_OutputImage; SmartPointer m_Function; /** A list of locations to start the recursive fill */ std::vector m_StartIndices; /** The origin of the source image */ typename ImageType::PointType m_ImageOrigin; /** The spacing of the source image */ typename ImageType::SpacingType m_ImageSpacing; /** Region of the source image */ RegionType m_ImageRegion; bool m_UpwardsExpansion; int m_InitializeValue; void ExpandThresholdUpwards(); void ExpandThresholdDownwards(); void IncrementRegionGrowingState(); //calculates how many steps the voxel is from the current step int EstimateDistance(IndexType); //calculates how many expansion steps will be taken unsigned int CalculateMaxRGS(); private: void InsertIndexTypeIntoQueueMap (unsigned int key, IndexType index); int m_RegionGrowingState; QueueMapType m_QueueMap; int m_MinTH; int m_MaxTH; int m_SeedPointValue; unsigned int m_VoxelCounter; unsigned int m_LastVoxelNumber; int m_DetectedLeakagePoint; float m_CurrentLeakageRatio; void CheckSeedPointValue(); /* flag for switching between raw leakage detection (bigger bronchial vessels) * and fine leakage detection (smaller bronchial vessels [starting from leaves]) */ bool m_FineDetectionMode; bool m_DetectionStop; }; }//end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkAdaptiveThresholdIterator.txx" #endif #endif diff --git a/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.txx b/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.txx index 339d58b8a0..7bf27b796f 100644 --- a/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.txx +++ b/Modules/Segmentation/Algorithms/itkAdaptiveThresholdIterator.txx @@ -1,464 +1,479 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _itkAdaptiveThresholdIterator_txx #define _itkAdaptiveThresholdIterator_txx #include "itkAdaptiveThresholdIterator.h" #include "mitkProgressBar.h" #include namespace itk { template AdaptiveThresholdIterator ::AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr, IndexType startIndex) :m_FineDetectionMode(false), m_DetectionStop(false) { this->m_OutputImage = imagePtr; m_Function = fnPtr; m_StartIndices.push_back ( startIndex ); // Set up the temporary image this->InitializeIterator(); } template AdaptiveThresholdIterator ::AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr, std::vector& startIndex) :m_FineDetectionMode(false), m_DetectionStop(false) { this->m_OutputImage = imagePtr; m_Function = fnPtr; unsigned int i; for (i = 0; i < startIndex.size(); i++ ) { m_StartIndices.push_back ( startIndex[i] ); } // Set up the temporary image this->InitializeIterator(); } template AdaptiveThresholdIterator ::AdaptiveThresholdIterator(ImageType *imagePtr, FunctionType *fnPtr) :m_FineDetectionMode(false), m_DetectionStop(false) { this->m_OutputImage = imagePtr; //here we store the image, we have to wite the result to m_Function = fnPtr; // Set up the temporary image this->InitializeIterator(); } template void AdaptiveThresholdIterator ::InitializeIterator() { // Get the origin and spacing from the image in simple arrays m_ImageOrigin = this->m_OutputImage->GetOrigin(); m_ImageSpacing = this->m_OutputImage->GetSpacing(); m_ImageRegion = this->m_OutputImage->GetBufferedRegion(); this->InitRegionGrowingState(); m_VoxelCounter = 0; m_LastVoxelNumber = 0; m_CurrentLeakageRatio = 0; m_DetectedLeakagePoint = 0; } template void AdaptiveThresholdIterator ::SetExpansionDirection(bool upwards) { m_UpwardsExpansion = upwards; } template void AdaptiveThresholdIterator ::IncrementRegionGrowingState() { //make the progressbar go one step further if(!m_FineDetectionMode) mitk::ProgressBar::GetInstance()->Progress(); //updating the thresholds if (m_UpwardsExpansion) { this->ExpandThresholdUpwards(); } else { this->ExpandThresholdDownwards(); } //leakage-detection int criticalValue = 2000;// calculate a bit more "intelligent" if (! m_FineDetectionMode) { int diff = m_VoxelCounter - m_LastVoxelNumber; if (diff > m_CurrentLeakageRatio) { m_CurrentLeakageRatio = diff; m_DetectedLeakagePoint = m_RegionGrowingState; } m_LastVoxelNumber = m_VoxelCounter; m_VoxelCounter = 0; } else //fine leakage detection { //counting voxels over interations; if above a critical value (to be extended) then set this to leakage int diff = m_VoxelCounter - m_LastVoxelNumber; //std::cout<<"diff is: "< void AdaptiveThresholdIterator ::ExpandThresholdUpwards() { int upper = (int) m_Function->GetUpper(); upper++; m_Function->ThresholdBetween(m_MinTH, upper); } template void AdaptiveThresholdIterator ::ExpandThresholdDownwards() { int lower = (int) m_Function->GetLower(); lower--; m_Function->ThresholdBetween(lower, m_MaxTH); } template void AdaptiveThresholdIterator ::InitRegionGrowingState() { this->m_RegionGrowingState = 1; } template int AdaptiveThresholdIterator ::EstimateDistance(IndexType tempIndex) { PixelType value = this->m_Function->GetInputImage()->GetPixel(tempIndex); PixelType minPixel = PixelType(m_MinTH); PixelType maxPixel = PixelType(m_MaxTH); if (value > maxPixel || value < minPixel) { return 0; } if (m_UpwardsExpansion) { return (int)(value - m_SeedPointValue ); } else { return (int)( m_SeedPointValue - value ); } } template void AdaptiveThresholdIterator ::SetMinTH(int min) { m_MinTH = min; } template void AdaptiveThresholdIterator ::SetMaxTH(int max) { m_MaxTH = max; } template int AdaptiveThresholdIterator ::GetSeedPointValue() { return this->m_SeedPointValue; } template void AdaptiveThresholdIterator ::GoToBegin() { m_QueueMap.clear(); m_SeedPointValue = 0; IndexType seedIndex = m_StartIndices[0]; bool doAverage = false; //enable or disable manually! if (doAverage) { //loops for creating the sum of the N27-neighborhood around the seedpoint for (int i = -1; i<=1; i++) { for (int j = -1; j<=1; j++) { for (int k = -1; k<=1; k++) { seedIndex[0]=seedIndex[0]+i; seedIndex[1]=seedIndex[1]+j; seedIndex[2]=seedIndex[2]+k; m_SeedPointValue += (int) m_Function->GetInputImage()->GetPixel(seedIndex); } } } //value of seedpoint computed from mean of N27-neighborhood m_SeedPointValue = m_SeedPointValue / 27; } else { m_SeedPointValue = (int) m_Function->GetInputImage()->GetPixel(seedIndex); } this->CheckSeedPointValue(); m_InitializeValue = (this->CalculateMaxRGS() +1); if(!m_FineDetectionMode) mitk::ProgressBar::GetInstance()->AddStepsToDo(m_InitializeValue-1); //only initialize with zeros for the first segmention (raw segmentation mode) if(!m_FineDetectionMode) { this->m_OutputImage->FillBuffer((PixelType) 0 ); } if (m_UpwardsExpansion) { m_Function->ThresholdBetween(m_MinTH, m_SeedPointValue); } else { m_Function->ThresholdBetween(m_SeedPointValue, m_MaxTH); } this->m_IsAtEnd = true; seedIndex = m_StartIndices[0];// warum noch mal? Steht doch schon in Zeile 224 if( this->m_OutputImage->GetBufferedRegion().IsInside (seedIndex ) && this->m_SeedPointValue > this->m_MinTH && this->m_SeedPointValue < this->m_MaxTH) { // Push the seed onto the queue this->InsertIndexTypeIntoQueueMap(m_RegionGrowingState, seedIndex); // Obviously, we're at the beginning this->m_IsAtEnd = false; this->m_OutputImage->SetPixel(seedIndex, (m_InitializeValue - m_RegionGrowingState)); } } template void AdaptiveThresholdIterator ::CheckSeedPointValue () { //checks, if the value, that has been averaged over the N-27 neighborhood aorund the seedpoint is still inside //the thresholds-ranges. if not, the actual value of the seedpoint (not averaged) is used if (m_SeedPointValue < m_MinTH || m_SeedPointValue > m_MaxTH) { m_SeedPointValue = (int) m_Function->GetInputImage()->GetPixel(m_StartIndices[0]); } } template unsigned int AdaptiveThresholdIterator ::CalculateMaxRGS () { if (m_UpwardsExpansion) { return (m_MaxTH-m_SeedPointValue); } else { return (m_SeedPointValue-m_MinTH); } } template bool AdaptiveThresholdIterator ::IsPixelIncluded(const IndexType & index) const { //checks, if grayvalue of current voxel is inside the currently used thresholds return this->m_Function->EvaluateAtIndex(index); } template void AdaptiveThresholdIterator ::InsertIndexTypeIntoQueueMap (unsigned int key, IndexType index) { //first check if the key-specific queue already exists if (m_QueueMap.count(key) == 0) { //if queue doesn´t exist, create it, push the IndexType onto it //and insert it into the map IndexQueueType newQueue; newQueue.push(index); typedef typename QueueMapType::value_type KeyIndexQueue; m_QueueMap.insert(KeyIndexQueue(key, newQueue)); } else { //if queue already exists in the map, push IndexType onto its specific queue (* (m_QueueMap.find(key)) ).second.push(index); } } template void AdaptiveThresholdIterator ::DoExtendedFloodStep() { // The index in the front of the queue should always be // valid and be inside since this is what the iterator // uses in the Set/Get methods. This is ensured by the // GoToBegin() method. typename QueueMapType::iterator currentIt = m_QueueMap.find(m_RegionGrowingState); if (currentIt == m_QueueMap.end()) { this->IncrementRegionGrowingState(); } else { IndexQueueType* currentQueue = & (* currentIt).second; // Take the index in the front of the queue const IndexType & topIndex = currentQueue->front(); // Iterate through all possible dimensions // NOTE: Replace this with a ShapeNeighborhoodIterator for(unsigned int i=0; im_OutputImage->GetPixel( tempIndex ) == 0 ) { // if it is inside, push it into the queue if( this->IsPixelIncluded( tempIndex ) ) { //hier wird Voxel in momentan aktiven Stack und ins OutputImage geschrieben this->InsertIndexTypeIntoQueueMap( (m_RegionGrowingState ),tempIndex); this->m_OutputImage->SetPixel( tempIndex, (m_InitializeValue - m_RegionGrowingState)); } else // If the pixel is not inside the current threshold { int distance = this->EstimateDistance(tempIndex); // [!] sollte nicht estimateDistance sondern calculateDistance() heißen! if (distance != 0) { //hier wird Voxel in entsprechenden Stack und ins OutputImage geschrieben this->InsertIndexTypeIntoQueueMap( (distance),tempIndex); this->m_OutputImage->SetPixel( tempIndex, (m_InitializeValue - distance)); } } } } } // end left/right neighbor loop } // end check all neighbors // Now that all the potential neighbors have been // inserted we can get rid of the pixel in the front currentQueue->pop(); m_VoxelCounter++; if( currentQueue->empty()) { //if currently used queue is empty this->IncrementRegionGrowingState(); } } if (m_RegionGrowingState >= (m_InitializeValue) || m_DetectionStop) { this->m_IsAtEnd = true; // std::cout << "RegionGrowing finished !" << std::endl; // std::cout << "Detected point of leakage: " << m_DetectedLeakagePoint << std::endl; } } }//end namespace itk #endif diff --git a/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.h b/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.h index fcf4590e8e..dbce67d0d7 100644 --- a/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.h +++ b/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.h @@ -1,120 +1,135 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef __itkConnectedAdaptiveThresholdImageFilter_h #define __itkConnectedAdaptiveThresholdImageFilter_h #include "itkImage.h" #include "itkConnectedThresholdImageFilter.h" namespace itk { /** /class ConnectedAdaptiveThreholdImageFilter * \brief ImageFilter used for processing an image with an adaptive * iterator (such as itkAdaptiveThresholdIterator) * * \ingroup RegionGrowingSegmentation */ template class ITK_EXPORT ConnectedAdaptiveThresholdImageFilter: public ConnectedThresholdImageFilter { public: /** Standard class typedefs. */ typedef ConnectedAdaptiveThresholdImageFilter Self; typedef ConnectedThresholdImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Run-time type information (and related methods). */ itkTypeMacro(ConnectedAdaptiveThresholdImageFilter, ConnectedThresholdImageFilter); typedef TInputImage InputImageType; typedef TOutputImage OutputImageType; typedef typename OutputImageType::Pointer OutputImagePointer; typedef typename InputImageType::IndexType IndexType; typedef typename InputImageType::PixelType PixelType; void SetGrowingDirectionIsUpwards(bool upwards) { m_GrowingDirectionIsUpwards = upwards; } /* Switch between fine and raw leakage detection. */ void SetFineDetectionMode(bool fine) {m_FineDetectionMode = fine; m_DiscardLastPreview = false;} int GetSeedpointValue(void) {return m_SeedpointValue;} int GetLeakagePoint(void) {return m_DetectedLeakagePoint;} bool m_SegmentationCancelled; /* * Correct the position of the seed point, only performed if seed point value is outside threshold range * @param sizeOfVolume edge length of the square volume in which the search for a "better" seed is performed */ IndexType CorrectSeedPointPosition(unsigned int sizeOfVolume, int lowerTh, int upperTh); /* Sets all voxels in a square volume with the size of @param croppingSize * and the center point equal to @param seedPoint to the value zero. */ void CropMask(unsigned int croppingSize); /* Modifies the iterator mask to keep all previous segmentation results in the same mask. * @returnParam largest value in the segmentation mask */ unsigned int AdjustIteratorMask(); /* Sets parameters needed for adjusting the iterator mask * @param iteratorMaskForFineSegmentation pointer to the image containing the complete segmentation result of one leaf (inclusively leakage-segmentation) * @param adjLowerTh lower threshold value of the segmentation without leakage-segmentation * @param adjLowerTh upper threshold value of the segmentation without leakage-segmentation * @param discardLeafSegmentation flag if the last segmentation preview ended with a leakage already in the first step */ void SetParameterForFineSegmentation( TOutputImage * iteratorMaskForFineSegmentation ,unsigned int adjLowerTh, unsigned int adjUpperTh, itk::Index<3> seedPoint, bool discardLeafSegmentation); TOutputImage* GetResultImage(); protected: ConnectedAdaptiveThresholdImageFilter(); ~ConnectedAdaptiveThresholdImageFilter(){}; void GenerateData(); TOutputImage * m_IteratorMaskForFineSegmentation; private: OutputImagePointer m_OutoutImageMaskFineSegmentation; bool m_GrowingDirectionIsUpwards; PixelType m_SeedpointValue; PixelType m_DetectedLeakagePoint; PixelType m_InitValue ; unsigned int m_AdjLowerTh; unsigned int m_AdjUpperTh; itk::Index<3> m_SeedPointIndex; /* Flag for switching between raw segmentation and fine segmentation (Bronchial tree segmentation) */ bool m_FineDetectionMode; bool m_DiscardLastPreview; }; }// end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkConnectedAdaptiveThresholdImageFilter.txx" #endif #endif diff --git a/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.txx b/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.txx index ab5c3f5580..0886bb3d43 100644 --- a/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.txx +++ b/Modules/Segmentation/Algorithms/itkConnectedAdaptiveThresholdImageFilter.txx @@ -1,288 +1,303 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _itkConnectedAdaptiveThresholdImageFilter_txx #define _itkConnectedAdaptiveThresholdImageFilter_txx #include "itkConnectedAdaptiveThresholdImageFilter.h" #include "itkThresholdImageFilter.h" #include "itkBinaryThresholdImageFunction.h" #include "itkAdaptiveThresholdIterator.h" #include "itkMinimumMaximumImageFilter.h" namespace itk { /** * Constructor */ template ConnectedAdaptiveThresholdImageFilter ::ConnectedAdaptiveThresholdImageFilter() : m_FineDetectionMode(false) { } template void ConnectedAdaptiveThresholdImageFilter::GenerateData() { typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput(); typename ConnectedAdaptiveThresholdImageFilter::OutputImagePointer outputImage = this->GetOutput(); typename Superclass::InputPixelObjectType::Pointer lowerThreshold=this->GetLowerInput(); typename Superclass::InputPixelObjectType::Pointer upperThreshold=this->GetUpperInput(); //kommt drauf, wie wir hier die Pipeline aufbauen Superclass::m_Lower = lowerThreshold->Get(); Superclass::m_Upper = upperThreshold->Get(); typedef BinaryThresholdImageFunction FunctionType; typedef AdaptiveThresholdIterator IteratorType; int initValue = IteratorType::CalculateInitializeValue((int)Superclass::m_Lower, (int)Superclass::m_Upper); // Initialize the output according to the segmentation (fine or raw) if(m_FineDetectionMode) { outputImage = this->m_OutoutImageMaskFineSegmentation; } typename ConnectedAdaptiveThresholdImageFilter::OutputImageRegionType region = outputImage->GetRequestedRegion(); outputImage->SetBufferedRegion( region ); outputImage->Allocate(); if(!m_FineDetectionMode) { // only initalize the output image if we are using the raw segmentation mode outputImage->FillBuffer ((typename ConnectedAdaptiveThresholdImageFilter::OutputImagePixelType) initValue ); } typename FunctionType::Pointer function = FunctionType::New(); function->SetInputImage ( inputImage ); //pass parameters needed for region growing to iterator IteratorType it ( outputImage, function, this->m_SeedList ); it.SetFineDetectionMode(m_FineDetectionMode); it.SetExpansionDirection(m_GrowingDirectionIsUpwards); it.SetMinTH((int) Superclass::m_Lower); it.SetMaxTH((int) Superclass::m_Upper); it.GoToBegin(); this->m_SeedpointValue = it.GetSeedPointValue(); if (Superclass::m_Lower > this->m_SeedpointValue || this->m_SeedpointValue > Superclass::m_Upper) { //set m_SegmentationCancelled to true, so if it doesn't reach the point where it is set back to false //we can asssume that there was an error this->m_SegmentationCancelled = true; return; } //iterate through image until while( !it.IsAtEnd()) { //make iterator go one step further (calls method DoFloodStep()) ++it; } this->m_DetectedLeakagePoint = it.GetLeakagePoint(); this->m_SegmentationCancelled = false; } template TOutputImage* itk::ConnectedAdaptiveThresholdImageFilter::GetResultImage() { return m_OutoutImageMaskFineSegmentation; } template typename ConnectedAdaptiveThresholdImageFilter::IndexType itk::ConnectedAdaptiveThresholdImageFilter::CorrectSeedPointPosition(unsigned int sizeOfVolume, int lowerTh, int upperTh) { typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput(); typedef typename TInputImage::IndexType IndexType; IndexType itkIntelligentSeedIndex; int seedPixelValue = inputImage->GetPixel(m_SeedPointIndex); //set new seed index to the voxel with the darkest value and shortest distance to original seed if ( seedPixelValue > upperTh || seedPixelValue < lowerTh) { //MITK_INFO << "seed pixel value [BEFORE] = " << seedPixelValue; //ToDo crop region itk::Index<3> workindex; for(int i = 0; i < 3; i++) { workindex[i] = m_SeedPointIndex[i] - sizeOfVolume/2; if(workindex[i]<0) workindex[i]=0; } itk::Size<3> worksize; for(int i = 0; i < 3; i++) { worksize[i] = sizeOfVolume; } itk::ImageRegion<3> workregion(workindex, worksize); itk::ImageRegionIterator regionIt(const_cast(inputImage.GetPointer()), workregion); //int darkestGrayValue=seedPixelValue; int currentGrayValue; float distance = (float) (sizeOfVolume/2); float relativeDistance = 1; // between 0 and 1 mitk::Vector3D seedVector,currentVector; mitk::FillVector3D(seedVector,m_SeedPointIndex[0],m_SeedPointIndex[1],m_SeedPointIndex[2]); currentVector = seedVector; float costValue=0; //beware, Depending on seeking upper or lower value... for(regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt) { //get current gray value currentGrayValue = regionIt.Value(); //get current seed index m_SeedPointIndex = regionIt.GetIndex(); //fill current vector mitk::FillVector3D(currentVector,m_SeedPointIndex[0],m_SeedPointIndex[1],m_SeedPointIndex[2]); //calculate distance from original seed to new seed mitk::Vector3D distVector = currentVector - seedVector; distance = fabs(distVector.GetSquaredNorm()); relativeDistance = distance/(sizeOfVolume/2); //calculate "cost function" float currentCostValue = (1-relativeDistance)* currentGrayValue; if (currentCostValue < costValue && currentGrayValue < upperTh) { itkIntelligentSeedIndex = regionIt.GetIndex(); costValue = currentCostValue; //MITK_INFO <<"cost value="<< costValue; //MITK_INFO <<"darkest and closest Voxel ="<< currentGrayValue; //MITK_INFO <<"m_UPPER="<< upperTh; } } //MITK_INFO<< "seed pixel value [AFTER] =" << inputImage->GetPixel(itkIntelligentSeedIndex) <<"\n"; } else { // no correction of the seed point is needed, just pass the original seed itkIntelligentSeedIndex = m_SeedPointIndex; } return itkIntelligentSeedIndex; } template void itk::ConnectedAdaptiveThresholdImageFilter::CropMask(unsigned int croppingSize) { //initialize center point of the working region itk::Index<3> workindex; for(int i = 0; i < 3; i++) { workindex[i] = m_SeedPointIndex[i] - croppingSize/2; if(workindex[i]<0) workindex[i]=0; } // initialize working volume itk::Size<3> worksize; for(int i = 0; i < 3; i++) { worksize[i] = croppingSize; } // set working region itk::ImageRegion<3> workregion(workindex, worksize); //check if the entire region is inside the image if(!(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion().IsInside(workregion))) { // if not then crop to the intersection of the image (gemeinsame Schnittmenge Bild und workingRegion) if(!(workregion.Crop(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion()))) { MITK_ERROR<< "Cropping working region failed!"; return; } } // initialize region iterator itk::ImageRegionIterator regionIt(m_OutoutImageMaskFineSegmentation, workregion); for(regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt) { //and set all voxel inside the working region to zero regionIt.Set(0); } } template unsigned int itk::ConnectedAdaptiveThresholdImageFilter::AdjustIteratorMask() { typedef itk::ThresholdImageFilter ThresholdFilterType; typedef itk::MinimumMaximumImageFilter MaxFilterType; typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); typename MaxFilterType::Pointer maxFilter = MaxFilterType::New(); unsigned int maxValue; if(!m_DiscardLastPreview) { //get the biggest value of the image maxFilter->SetInput(m_OutoutImageMaskFineSegmentation); maxFilter->UpdateLargestPossibleRegion(); maxValue = maxFilter->GetMaximum(); } else { // use the last biggest value in the preview. This was set in SetParameterForFineSegmentation(...adjLowerTh...) [] maxValue = m_AdjLowerTh; } //set all values upper to zero (thresouldOutside uses < and > NOT <= and >=) thresholdFilter->SetInput(m_OutoutImageMaskFineSegmentation); thresholdFilter->SetOutsideValue(0); thresholdFilter->ThresholdOutside(m_AdjLowerTh, maxValue ); thresholdFilter->UpdateLargestPossibleRegion(); //set all values in between lower and upper (>=lower && <=upper) to the highest value in the image thresholdFilter->SetInput(thresholdFilter->GetOutput()); thresholdFilter->SetOutsideValue(maxValue); thresholdFilter->ThresholdOutside(0, m_AdjLowerTh-1); thresholdFilter->UpdateLargestPossibleRegion(); m_OutoutImageMaskFineSegmentation = thresholdFilter->GetOutput(); return maxValue; } template void itk::ConnectedAdaptiveThresholdImageFilter::SetParameterForFineSegmentation( TOutputImage * iteratorMaskForFineSegmentation ,unsigned int adjLowerTh, unsigned int adjUpperTh, itk::Index<3> seedPoint, bool discardLeafSegmentation) { //just to make sure we´re in the right mode and the mask exsits if(m_FineDetectionMode && iteratorMaskForFineSegmentation) { m_OutoutImageMaskFineSegmentation = iteratorMaskForFineSegmentation; m_AdjLowerTh = adjLowerTh; m_AdjUpperTh = adjUpperTh; //still needed? m_SeedPointIndex = seedPoint; m_DiscardLastPreview = discardLeafSegmentation; } else { if(!m_FineDetectionMode) { MITK_ERROR<< "Fine-detection-segmentation mode not set!"; } else { MITK_ERROR<< "Iterator-mask-image not set!"; } } } }//end namespace itk #endif diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp index bff731e33f..79e24d9edb 100644 --- a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp +++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp @@ -1,312 +1,320 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBinaryThresholdTool.h" #include "mitkBinaryThresholdTool.xpm" #include "mitkToolManager.h" #include "mitkBoundingObjectToSegmentationFilter.h" #include #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkOrganTypeProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkImageTimeSelector.h" #include #include #include "mitkPadImageFilter.h" #include "mitkMaskAndCutRoiImageFilter.h" namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, BinaryThresholdTool, "Thresholding tool"); } mitk::BinaryThresholdTool::BinaryThresholdTool() :m_SensibleMinimumThresholdValue(-100), m_SensibleMaximumThresholdValue(+100), m_CurrentThresholdValue(0.0), m_IsFloatImage(false) { this->SupportRoiOn(); m_ThresholdFeedbackNode = DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_ThresholdFeedbackNode ); m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) ); m_ThresholdFeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) ); m_ThresholdFeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) ); m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) ); m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") ); m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); } mitk::BinaryThresholdTool::~BinaryThresholdTool() { } const char** mitk::BinaryThresholdTool::GetXPM() const { return mitkBinaryThresholdTool_xpm; } const char* mitk::BinaryThresholdTool::GetName() const { return "Thresholding"; } void mitk::BinaryThresholdTool::Activated() { m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeForThresholding = m_OriginalImageNode; if ( m_NodeForThresholding.IsNotNull() ) { SetupPreviewNodeFor( m_NodeForThresholding ); } else { m_ToolManager->ActivateTool(-1); } } void mitk::BinaryThresholdTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_NodeForThresholding = NULL; m_OriginalImageNode = NULL; try { if (DataStorage* storage = m_ToolManager->GetDataStorage()) { storage->Remove( m_ThresholdFeedbackNode ); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch(...) { // don't care } m_ThresholdFeedbackNode->SetData(NULL); } void mitk::BinaryThresholdTool::SetThresholdValue(double value) { if (m_ThresholdFeedbackNode.IsNotNull()) { m_CurrentThresholdValue = value; m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 1) ) ); RenderingManager::GetInstance()->RequestUpdateAll(); } } void mitk::BinaryThresholdTool::AcceptCurrentThresholdValue(const std::string& organName, const Color& color) { CreateNewSegmentationFromThreshold(m_NodeForThresholding, organName, color ); RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::CancelThresholding() { m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::SetupPreviewNodeFor( DataNode* nodeForThresholding ) { if (nodeForThresholding) { Image::Pointer image = dynamic_cast( nodeForThresholding->GetData() ); Image::Pointer originalImage = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { // initialize and a new node with the same image as our reference image // use the level window property of this image copy to display the result of a thresholding operation m_ThresholdFeedbackNode->SetData( image ); int layer(50); nodeForThresholding->GetIntProperty("layer", layer); m_ThresholdFeedbackNode->SetIntProperty("layer", layer+1); if (DataStorage* storage = m_ToolManager->GetDataStorage()) { if (storage->Exists(m_ThresholdFeedbackNode)) storage->Remove(m_ThresholdFeedbackNode); storage->Add( m_ThresholdFeedbackNode, m_OriginalImageNode ); } if (image.GetPointer() == originalImage.GetPointer()) { if (originalImage->GetPixelType().GetPixelTypeId() == typeid(float)) m_IsFloatImage = true; else m_IsFloatImage = false; m_SensibleMinimumThresholdValue = static_cast( originalImage->GetScalarValueMin() ); m_SensibleMaximumThresholdValue = static_cast( originalImage->GetScalarValueMax() ); } LevelWindowProperty::Pointer lwp = dynamic_cast( m_ThresholdFeedbackNode->GetProperty( "levelwindow" )); if (lwp && !m_IsFloatImage ) { m_CurrentThresholdValue = static_cast( lwp->GetLevelWindow().GetLevel() ); } else { m_CurrentThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue)/2; } IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue, m_IsFloatImage); ThresholdingValueChanged.Send(m_CurrentThresholdValue); } } } void mitk::BinaryThresholdTool::CreateNewSegmentationFromThreshold(DataNode* node, const std::string& organName, const Color& color) { if (node) { Image::Pointer image = dynamic_cast( m_NodeForThresholding->GetData() ); if (image.IsNotNull()) { // create a new image of the same dimensions and smallest possible pixel type DataNode::Pointer emptySegmentation = Tool::CreateEmptySegmentationNode( image, organName, color ); if (emptySegmentation) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep) { try { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( image ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer image3D = timeSelector->GetOutput(); - AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast(emptySegmentation->GetData()), timeStep ); + + if (image3D->GetDimension() == 2) + { + AccessFixedDimensionByItk_2( image3D, ITKThresholding, 2, dynamic_cast(emptySegmentation->GetData()), timeStep ); + } + else + { + AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast(emptySegmentation->GetData()), timeStep ); + } } catch(...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); } } if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, dynamic_cast (emptySegmentation->GetData())); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); emptySegmentation->SetData(padFilter->GetOutput()); } if (DataStorage::Pointer storage = m_ToolManager->GetDataStorage()) { storage->Add( emptySegmentation, m_OriginalImageNode ); // add as a child, because the segmentation "derives" from the original } m_ToolManager->SetWorkingData( emptySegmentation ); } } } } template void mitk::BinaryThresholdTool::ITKThresholding( itk::Image* originalImage, Image* segmentation, unsigned int timeStep ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer segmentation3D = timeSelector->GetOutput(); typedef itk::Image< Tool::DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations SegmentationType::Pointer itkSegmentation; CastToItkImage( segmentation3D, itkSegmentation ); // iterate over original and segmentation typedef itk::ImageRegionConstIterator< itk::Image > InputIteratorType; typedef itk::ImageRegionIterator< SegmentationType > SegmentationIteratorType; InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() ); SegmentationIteratorType outputIterator( itkSegmentation, itkSegmentation->GetLargestPossibleRegion() ); inputIterator.GoToBegin(); outputIterator.GoToBegin(); while (!outputIterator.IsAtEnd()) { if ( inputIterator.Get() >= m_CurrentThresholdValue ) outputIterator.Set( 1 ); else outputIterator.Set( 0 ); ++inputIterator; ++outputIterator; } } void mitk::BinaryThresholdTool::OnRoiDataChanged() { mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast (m_NodeForThresholding->GetData()); if (image.IsNull()) return; mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); roiFilter->SetInput(image); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); mitk::DataNode::Pointer tmpNode = mitk::DataNode::New(); mitk::Image::Pointer tmpImage = roiFilter->GetOutput(); tmpNode->SetData(tmpImage); m_SensibleMaximumThresholdValue = static_cast (roiFilter->GetMaxValue()); m_SensibleMinimumThresholdValue = static_cast (roiFilter->GetMinValue()); SetupPreviewNodeFor( tmpNode ); m_NodeForThresholding = tmpNode; return; } else { this->SetupPreviewNodeFor(m_OriginalImageNode); m_NodeForThresholding = m_OriginalImageNode; return; } } diff --git a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp index c3e41bca80..f5c4e58c22 100644 --- a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp +++ b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp @@ -1,402 +1,402 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSegTool2D.h" #include "mitkToolManager.h" #include "mitkDataStorage.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkExtractImageFilter.h" #include "mitkExtractDirectedPlaneImageFilter.h" //Include of the new ImageExtractor #include "mitkExtractDirectedPlaneImageFilterNew.h" #include "mitkPlanarCircle.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkGetModuleContext.h" //Includes for 3DSurfaceInterpolation #include "mitkImageToContourFilter.h" #include "mitkSurfaceInterpolationController.h" #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) mitk::SegTool2D::SegTool2D(const char* type) :Tool(type), m_LastEventSender(NULL), m_LastEventSlice(0), m_Contourmarkername ("Position"), m_ShowMarkerNodes (true), m_3DInterpolationEnabled (true) { // great magic numbers CONNECT_ACTION( 80, OnMousePressed ); CONNECT_ACTION( 90, OnMouseMoved ); CONNECT_ACTION( 42, OnMouseReleased ); CONNECT_ACTION( 49014, OnInvertLogic ); } mitk::SegTool2D::~SegTool2D() { } bool mitk::SegTool2D::OnMousePressed (Action*, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( positionEvent->GetSender()->GetMapperID() != BaseRenderer::Standard2D ) return false; // we don't want anything but 2D m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); return true; } bool mitk::SegTool2D::OnMouseMoved (Action*, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( m_LastEventSender != positionEvent->GetSender() ) return false; if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false; return true; } bool mitk::SegTool2D::OnMouseReleased(Action*, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( m_LastEventSender != positionEvent->GetSender() ) return false; if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false; return true; } bool mitk::SegTool2D::OnInvertLogic(Action*, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( m_LastEventSender != positionEvent->GetSender() ) return false; if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false; return true; } bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice ) { assert(image); assert(plane); // compare normal of plane to the three axis vectors of the image Vector3D normal = plane->GetNormal(); Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0); Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1); Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2); normal.Normalize(); imageNormal0.Normalize(); imageNormal1.Normalize(); imageNormal2.Normalize(); imageNormal0.Set_vnl_vector( vnl_cross_3d(normal.Get_vnl_vector(),imageNormal0.Get_vnl_vector()) ); imageNormal1.Set_vnl_vector( vnl_cross_3d(normal.Get_vnl_vector(),imageNormal1.Get_vnl_vector()) ); imageNormal2.Set_vnl_vector( vnl_cross_3d(normal.Get_vnl_vector(),imageNormal2.Get_vnl_vector()) ); double eps( 0.00001 ); // transversal if ( imageNormal2.GetNorm() <= eps ) { affectedDimension = 2; } // sagittal else if ( imageNormal1.GetNorm() <= eps ) { affectedDimension = 1; } // frontal else if ( imageNormal0.GetNorm() <= eps ) { affectedDimension = 0; } else { affectedDimension = -1; // no idea return false; } // determine slice number in image Geometry3D* imageGeometry = image->GetGeometry(0); Point3D testPoint = imageGeometry->GetCenter(); Point3D projectedPoint; plane->Project( testPoint, projectedPoint ); Point3D indexPoint; imageGeometry->WorldToIndex( projectedPoint, indexPoint ); affectedSlice = ROUND( indexPoint[affectedDimension] ); MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice; // check if this index is still within the image if ( affectedSlice < 0 || affectedSlice >= static_cast(image->GetDimension(affectedDimension)) ) return false; return true; } mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const PositionEvent* positionEvent, const Image* image) { if (!positionEvent) return NULL; assert( positionEvent->GetSender() ); // sure, right? unsigned int timeStep = positionEvent->GetSender()->GetTimeStep( image ); // get the timestep of the visible part (time-wise) of the image // first, we determine, which slice is affected const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); if ( !image || !planeGeometry ) return NULL; int affectedDimension( -1 ); int affectedSlice( -1 ); - DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ); + //DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ); if ( DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ) ) { try { // now we extract the correct slice from the volume, resulting in a 2D image ExtractImageFilter::Pointer extractor= ExtractImageFilter::New(); extractor->SetInput( image ); extractor->SetSliceDimension( affectedDimension ); extractor->SetSliceIndex( affectedSlice ); extractor->SetTimeStep( timeStep ); extractor->Update(); // here we have a single slice that can be modified Image::Pointer slice = extractor->GetOutput(); //Workaround because of bug #7079 Point3D origin = slice->GetGeometry()->GetOrigin(); int affectedDimension(-1); if(positionEvent->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")) { affectedDimension = 2; } if(positionEvent->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2")) { affectedDimension = 0; } if(positionEvent->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")) { affectedDimension = 1; } if (affectedDimension != -1) { origin[affectedDimension] = planeGeometry->GetOrigin()[affectedDimension]; slice->GetGeometry()->SetOrigin(origin); } //Workaround end return slice; } catch(...) { // not working return NULL; } } else { ExtractDirectedPlaneImageFilterNew::Pointer newExtractor = ExtractDirectedPlaneImageFilterNew::New(); newExtractor->SetInput( image ); newExtractor->SetActualInputTimestep( timeStep ); newExtractor->SetCurrentWorldGeometry2D( planeGeometry ); newExtractor->Update(); Image::Pointer slice = newExtractor->GetOutput(); return slice; } } mitk::Image::Pointer mitk::SegTool2D::GetAffectedWorkingSlice(const PositionEvent* positionEvent) { DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if ( !workingNode ) return NULL; Image* workingImage = dynamic_cast(workingNode->GetData()); if ( !workingImage ) return NULL; return GetAffectedImageSliceAs2DImage( positionEvent, workingImage ); } mitk::Image::Pointer mitk::SegTool2D::GetAffectedReferenceSlice(const PositionEvent* positionEvent) { DataNode* referenceNode( m_ToolManager->GetReferenceData(0) ); if ( !referenceNode ) return NULL; Image* referenceImage = dynamic_cast(referenceNode->GetData()); if ( !referenceImage ) return NULL; return GetAffectedImageSliceAs2DImage( positionEvent, referenceImage ); } void mitk::SegTool2D::WriteBackSegmentationResult (const PositionEvent* positionEvent, Image* slice) { const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); Image* image = dynamic_cast(workingNode->GetData()); int affectedDimension( -1 ); int affectedSlice( -1 ); DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ); if (affectedDimension != -1) { OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New(); slicewriter->SetInput( image ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( slice ); slicewriter->SetSliceDimension( affectedDimension ); slicewriter->SetSliceIndex( affectedSlice ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) ); slicewriter->Update(); } else { OverwriteDirectedPlaneImageFilter::Pointer slicewriter = OverwriteDirectedPlaneImageFilter::New(); slicewriter->SetInput( image ); slicewriter->SetCreateUndoInformation( false ); slicewriter->SetSliceImage( slice ); slicewriter->SetPlaneGeometry3D( slice->GetGeometry() ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) ); slicewriter->Update(); } if ( m_3DInterpolationEnabled ) { slice->DisconnectPipeline(); ImageToContourFilter::Pointer contourExtractor = ImageToContourFilter::New(); contourExtractor->SetInput(slice); contourExtractor->Update(); mitk::Surface::Pointer contour = contourExtractor->GetOutput(); if (contour->GetVtkPolyData()->GetNumberOfPoints() > 0 ) { unsigned int pos = this->AddContourmarker(positionEvent); mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); PlanePositionManagerService* service = dynamic_cast(mitk::GetModuleContext()->GetService(serviceRef)); mitk::SurfaceInterpolationController::GetInstance()->AddNewContour( contour, service->GetPlanePosition(pos)); contour->DisconnectPipeline(); } } } void mitk::SegTool2D::SetShowMarkerNodes(bool status) { m_ShowMarkerNodes = status; } void mitk::SegTool2D::Enable3DInterpolation(bool status) { m_3DInterpolationEnabled = status; } unsigned int mitk::SegTool2D::AddContourmarker ( const PositionEvent* positionEvent ) { const mitk::Geometry2D* plane = dynamic_cast (dynamic_cast< const mitk::SlicedGeometry3D*>( positionEvent->GetSender()->GetSliceNavigationController()->GetCurrentGeometry3D())->GetGeometry2D(0)); mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); PlanePositionManagerService* service = dynamic_cast(mitk::GetModuleContext()->GetService(serviceRef)); unsigned int size = service->GetNumberOfPlanePositions(); unsigned int id = service->AddNewPlanePosition(plane, positionEvent->GetSender()->GetSliceNavigationController()->GetSlice()->GetPos()); mitk::PlanarCircle::Pointer contourMarker = mitk::PlanarCircle::New(); contourMarker->SetGeometry2D( const_cast(plane)); std::stringstream markerStream; mitk::DataNode* workingNode (m_ToolManager->GetWorkingData(0)); markerStream << m_Contourmarkername ; markerStream << " "; markerStream << id+1; DataNode::Pointer rotatedContourNode = DataNode::New(); rotatedContourNode->SetData(contourMarker); rotatedContourNode->SetProperty( "name", StringProperty::New(markerStream.str()) ); rotatedContourNode->SetProperty( "isContourMarker", BoolProperty::New(true)); rotatedContourNode->SetBoolProperty( "PlanarFigureInitializedWindow", true, positionEvent->GetSender() ); rotatedContourNode->SetProperty( "includeInBoundingBox", BoolProperty::New(false)); rotatedContourNode->SetProperty( "helper object", mitk::BoolProperty::New(!m_ShowMarkerNodes)); if (plane) { if ( id == size ) { m_ToolManager->GetDataStorage()->Add(rotatedContourNode, workingNode); } else { mitk::NodePredicateProperty::Pointer isMarker = mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)); mitk::DataStorage::SetOfObjects::ConstPointer markers = m_ToolManager->GetDataStorage()->GetDerivations(workingNode,isMarker); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = markers->begin(); iter != markers->end(); ++iter) { std::string nodeName = (*iter)->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int markerId = atof(nodeName.substr(t+1).c_str())-1; if(id == markerId) { return id; } } m_ToolManager->GetDataStorage()->Add(rotatedContourNode, workingNode); } } return id; } void mitk::SegTool2D::InteractiveSegmentationBugMessage( const std::string& message ) { MITK_ERROR << "********************************************************************************" << std::endl << " " << message << std::endl << "********************************************************************************" << std::endl << " " << std::endl << " If your image is rotated or the 2D views don't really contain the patient image, try to press the button next to the image selection. " << std::endl << " " << std::endl << " Please file a BUG REPORT: " << std::endl << " http://bugs.mitk.org" << std::endl << " Contain the following information:" << std::endl << " - What image were you working on?" << std::endl << " - Which region of the image?" << std::endl << " - Which tool did you use?" << std::endl << " - What did you do?" << std::endl << " - What happened (not)? What did you expect?" << std::endl; } diff --git a/Modules/ToFHardware/CMakeLists.txt b/Modules/ToFHardware/CMakeLists.txt index 22f063037b..efce2913ba 100644 --- a/Modules/ToFHardware/CMakeLists.txt +++ b/Modules/ToFHardware/CMakeLists.txt @@ -1,34 +1,39 @@ include(mitkToFHardware.cmake) if(MITK_USE_TOF_PMDCAMCUBE) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_PMD_SDK_DIR}/include) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_PMD_LIB}) endif(MITK_USE_TOF_PMDCAMCUBE) if(MITK_USE_TOF_O3) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_PMD_SDK_DIR}/include) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_PMD_LIB}) endif(MITK_USE_TOF_O3) if(MITK_USE_TOF_PMDCAMBOARD) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_PMD_SDK_DIR}/include) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_PMD_LIB}) endif(MITK_USE_TOF_PMDCAMBOARD) if(MITK_USE_TOF_MESASR4000) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_MESA_SDK_DIR}/include) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MESA_LIB}) endif(MITK_USE_TOF_MESASR4000) +IF(MITK_USE_TOF_KINECT) + SET(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_KINECT_INCLUDE_DIR}) + SET(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_KINECT_LIB}) +ENDIF(MITK_USE_TOF_KINECT) + MITK_CREATE_MODULE(mitkToFHardware SUBPROJECTS MITK-ToF INCLUDE_DIRS ${MITK_BIN_DIR} INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} DEPENDS Mitk MitkExt mitkOpenCVVideoSupport MitkIGT LegacyAdaptors EXPORT_DEFINE MITK_TOFHARDWARE_EXPORT ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ) add_subdirectory(Testing) diff --git a/Modules/ToFHardware/Testing/files.cmake b/Modules/ToFHardware/Testing/files.cmake index c2997f92f5..c4a1a1d76a 100644 --- a/Modules/ToFHardware/Testing/files.cmake +++ b/Modules/ToFHardware/Testing/files.cmake @@ -1,29 +1,30 @@ set(MODULE_TESTS mitkThreadedToFRawDataReconstructionTest.cpp mitkToFCameraMITKPlayerControllerTest.cpp - mitkToFCameraMITKPlayerDeviceTest.cpp + #mitkToFCameraMITKPlayerDeviceTest.cpp mitkToFCameraPMDCamBoardControllerTest.cpp mitkToFCameraPMDCamBoardDeviceTest.cpp #mitkToFCameraPMDRawDataCamBoardDeviceTest.cpp mitkToFCameraPMDCamCubeControllerTest.cpp mitkToFCameraPMDCamCubeDeviceTest.cpp #mitkToFCameraPMDRawDataCamCubeDeviceTest.cpp mitkToFCameraPMDControllerTest.cpp mitkToFCameraPMDDeviceTest.cpp mitkToFCameraPMDRawDataDeviceTest.cpp mitkToFCameraPMDMITKPlayerControllerTest.cpp mitkToFCameraPMDMITKPlayerDeviceTest.cpp mitkToFCameraPMDO3ControllerTest.cpp mitkToFCameraPMDO3DeviceTest.cpp mitkToFCameraPMDPlayerControllerTest.cpp mitkToFCameraPMDPlayerDeviceTest.cpp mitkToFImageCsvWriterTest.cpp mitkToFImageGrabberTest.cpp - mitkToFImageRecorderTest.cpp - mitkToFImageRecorderFilterTest.cpp + #mitkToFImageRecorderTest.cpp + #mitkToFImageRecorderFilterTest.cpp mitkToFImageWriterTest.cpp - mitkToFNrrdImageWriterTest.cpp - mitkToFPicImageWriterTest.cpp + #mitkToFNrrdImageWriterTest.cpp mitkToFOpenCVImageGrabberTest.cpp + #mitkKinectControllerTest.cpp + #mitkKinectDeviceTest.cpp ) diff --git a/Modules/ToFHardware/Testing/mitkKinectControllerTest.cpp b/Modules/ToFHardware/Testing/mitkKinectControllerTest.cpp new file mode 100644 index 0000000000..a7cb121f6f --- /dev/null +++ b/Modules/ToFHardware/Testing/mitkKinectControllerTest.cpp @@ -0,0 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +/**Documentation + * test for the class "KinectController". + */ +int mitkKinectControllerTest(int /* argc */, char* /*argv*/[]) +{ + + MITK_TEST_BEGIN("KinectController"); + + mitk::KinectController::Pointer testObject = mitk::KinectController::New(); + MITK_TEST_CONDITION_REQUIRED(!testObject.GetPointer()==NULL,"Testing initialzation!"); + MITK_TEST_CONDITION_REQUIRED(testObject->GetCaptureHeight()== 480 ,"Testing initialization of CaptureHeight"); + MITK_TEST_CONDITION_REQUIRED(testObject->GetCaptureWidth()== 640 ,"Testing initialization of CaptureWidth"); + MITK_TEST_CONDITION_REQUIRED(testObject->OpenCameraConnection(),"Testing opening of camera connection!"); + MITK_TEST_CONDITION_REQUIRED(testObject->UpdateCamera(),"Testing UpdateCamera()"); + MITK_TEST_CONDITION_REQUIRED(testObject->CloseCameraConnection(),"Testing closing of camera connection!"); + + MITK_TEST_END(); + +} + + diff --git a/Modules/ToFHardware/Testing/mitkKinectDeviceTest.cpp b/Modules/ToFHardware/Testing/mitkKinectDeviceTest.cpp new file mode 100644 index 0000000000..0e7be377bf --- /dev/null +++ b/Modules/ToFHardware/Testing/mitkKinectDeviceTest.cpp @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +/**Documentation + * test for the class "KinectDevice". + */ +int mitkKinectDeviceTest(int /* argc */, char* /*argv*/[]) +{ + + MITK_TEST_BEGIN("KinectDevice"); + + mitk::KinectDevice::Pointer testObject = mitk::KinectDevice::New(); + + MITK_TEST_CONDITION_REQUIRED(!testObject.GetPointer()==NULL,"Testing initialzation!"); + MITK_TEST_CONDITION_REQUIRED(testObject->ConnectCamera(),"Testing ConnectCamera()"); + MITK_TEST_OUTPUT(<<"Testing StartCamera()"); + testObject->StartCamera(); + int captureHeight = testObject->GetCaptureHeight(); + int captureWidth = testObject->GetCaptureWidth(); + MITK_TEST_CONDITION_REQUIRED(captureHeight== 480 ,"Testing initialization of CaptureHeight"); + MITK_TEST_CONDITION_REQUIRED(captureWidth== 640 ,"Testing initialization of CaptureWidth"); + // + MITK_TEST_OUTPUT(<<"Testing StopCamera()"); + testObject->StopCamera(); + MITK_TEST_CONDITION_REQUIRED(testObject->DisconnectCamera(),"Testing DisconnectCamera()"); + + MITK_TEST_END(); + +} diff --git a/Modules/ToFHardware/Testing/mitkToFPicImageWriterTest.cpp b/Modules/ToFHardware/Testing/mitkToFPicImageWriterTest.cpp deleted file mode 100644 index 6ad86ac061..0000000000 --- a/Modules/ToFHardware/Testing/mitkToFPicImageWriterTest.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include -#include -#include -#include -#include -#include - -/**Documentation - * test for the class "ToFPicImageWriter". - */ -int mitkToFPicImageWriterTest(int /* argc */, char* /*argv*/[]) -{ - MITK_TEST_BEGIN("ToFPicImageWriter"); - - mitk::ToFPicImageWriter::Pointer tofPicWriter = mitk::ToFPicImageWriter::New(); - MITK_TEST_CONDITION_REQUIRED(tofPicWriter.GetPointer(), "Testing initialization of test object!"); - MITK_TEST_CONDITION_REQUIRED(tofPicWriter->GetExtension() == ".pic", "Testing initialization of extension member variable!"); - - //run the test with some unusual parameters - unsigned int dimX = 255; - unsigned int dimY = 188; - unsigned int pixelNumber = dimX*dimY; - unsigned int numOfFrames = 117; //or numberOfSlices - - //create 3 images filled with random values - mitk::Image::Pointer distanceImage = mitk::ImageGenerator::GenerateRandomImage(dimX, dimY, numOfFrames,0); - mitk::Image::Pointer amplitudeImage = mitk::ImageGenerator::GenerateRandomImage(dimX, dimY, numOfFrames,0); - mitk::Image::Pointer intensityImage = mitk::ImageGenerator::GenerateRandomImage(dimX, dimY, numOfFrames,0); - - //file names on the disc - std::string distanceImageFileName("distImg.pic"); - std::string amplitudeImageFileName("amplImg.pic"); - std::string intensityImageFileName("intImg.pic"); - - tofPicWriter->SetDistanceImageFileName(distanceImageFileName); - tofPicWriter->SetAmplitudeImageFileName(amplitudeImageFileName); - tofPicWriter->SetIntensityImageFileName(intensityImageFileName); - tofPicWriter->SetCaptureWidth(dimX); - tofPicWriter->SetCaptureHeight(dimY); - tofPicWriter->SetToFImageType(mitk::ToFImageWriter::ToFImageType3D); - - //buffer for each slice - float* distanceArray; - float* amplitudeArray; - float* intensityArray; - - float* distanceArrayRead; - float* amplitudeArrayRead; - float* intensityArrayRead; - - tofPicWriter->Open(); //open file/stream - //Note: the slices are written out reverse order, because the ToFPicImageWriter has to write them out immediately. - //A PicFileWriter would write them out vice versa and the PicFileWriter reads the slices vice versa. - - for(unsigned int i = numOfFrames; i > 0 ; i--) - { //write values to file/stream - //The slice index is "i-1", because "for(unsigned int i = numOfFrames-1; i >= 0 ; i--)" does not work for some reason - distanceArray = (float*)distanceImage->GetSliceData(i-1, 0, 0)->GetData(); - amplitudeArray = (float*)amplitudeImage->GetSliceData(i-1, 0, 0)->GetData(); - intensityArray = (float*)intensityImage->GetSliceData(i-1, 0, 0)->GetData(); - - //write (or add) the three slices to the file - tofPicWriter->Add(distanceArray, amplitudeArray, intensityArray); - } - tofPicWriter->Close(); //close file - - //read in the three images from disc - mitk::PicFileReader::Pointer fileReader = mitk::PicFileReader::New(); - fileReader->SetFileName(distanceImageFileName); - fileReader->Update(); - mitk::Image::Pointer distanceImageRead = fileReader->GetOutput(); - - fileReader = mitk::PicFileReader::New(); - fileReader->SetFileName(amplitudeImageFileName); - fileReader->Update(); - mitk::Image::Pointer amplitudeImageRead = fileReader->GetOutput(); - - fileReader = mitk::PicFileReader::New(); - fileReader->SetFileName(intensityImageFileName); - fileReader->Update(); - mitk::Image::Pointer intensityImageRead = fileReader->GetOutput(); - - bool readingCorrect = true; - // for all frames... - for(unsigned int j=0; jGetSliceData(j, 0, 0)->GetData(); - amplitudeArray = (float*)amplitudeImage->GetSliceData(j, 0, 0)->GetData(); - intensityArray = (float*)intensityImage->GetSliceData(j, 0, 0)->GetData(); - - //data read from disc - distanceArrayRead = (float*)distanceImageRead->GetSliceData(j, 0, 0)->GetData(); - amplitudeArrayRead = (float*)amplitudeImageRead->GetSliceData(j, 0, 0)->GetData(); - intensityArrayRead = (float*)intensityImageRead->GetSliceData(j, 0, 0)->GetData(); - - //for all pixels -for(unsigned int i=0; i +#endif + +namespace mitk +{ +class KinectController::KinectControllerPrivate +{ +public: + KinectControllerPrivate(); + ~KinectControllerPrivate(); + + bool ErrorText(unsigned int error); +#ifdef MITK_USE_TOF_KINECT + xn::Context m_Context; ///< OpenNI context + xn::DepthGenerator m_DepthGenerator; ///< Depth generator to access depth image of kinect + xn::ImageGenerator m_ImageGenerator; ///< Image generator to access RGB image of kinect + xn::IRGenerator m_IRGenerator; ///< IR generator to access IR image of kinect +#endif + + bool m_ConnectionCheck; ///< check if camera is connected or not + + bool m_UseIR; ///< flag indicating whether IR image is used or not + + unsigned int m_CaptureWidth; ///< image width + unsigned int m_CaptureHeight; ///< image height +}; + +KinectController::KinectControllerPrivate::KinectControllerPrivate(): + m_Context(NULL), + m_DepthGenerator(NULL), + m_ImageGenerator(NULL), + m_IRGenerator(NULL), + m_ConnectionCheck(false), + m_UseIR(false), + m_CaptureWidth(640), + m_CaptureHeight(480) +{ +} + +KinectController::KinectControllerPrivate::~KinectControllerPrivate() +{ +} + +bool KinectController::KinectControllerPrivate::ErrorText(unsigned int error) +{ + if(error != XN_STATUS_OK) + { + MITK_ERROR << "Camera Error " << xnGetStatusString(error); + return false; + } + else return true; +} + +KinectController::KinectController(): d(new KinectControllerPrivate) +{ +} + +KinectController::~KinectController() +{ + delete d; + } + + bool KinectController::OpenCameraConnection() + { + if (!d->m_ConnectionCheck) + { + // Initialize the OpenNI status + d->m_ConnectionCheck = !d->ErrorText(d->m_Context.Init()); + // Create a depth generator and set its resolution + XnMapOutputMode DepthMode; + d->m_ConnectionCheck = !d->ErrorText(d->m_DepthGenerator.Create(d->m_Context)); + d->m_DepthGenerator.GetMapOutputMode(DepthMode); + DepthMode.nXRes = xn::Resolution((XnResolution)XN_RES_VGA).GetXResolution(); + DepthMode.nYRes = xn::Resolution((XnResolution)XN_RES_VGA).GetYResolution(); + d->m_ConnectionCheck = !d->ErrorText(d->m_DepthGenerator.SetMapOutputMode(DepthMode)); + + if (d->m_UseIR) + { + // Create the IR generator and set its resolution + d->m_ConnectionCheck = !d->ErrorText(d->m_IRGenerator.Create(d->m_Context)); + XnMapOutputMode IRMode; + d->m_IRGenerator.GetMapOutputMode(IRMode); + IRMode.nXRes = XN_VGA_X_RES; + IRMode.nYRes = XN_VGA_Y_RES; + IRMode.nFPS = 30; + d->m_ConnectionCheck = !d->ErrorText(d->m_IRGenerator.SetMapOutputMode(IRMode)); + } + else + { + // Create an image generator and set its resolution + XnMapOutputMode ImageMode; + d->m_ConnectionCheck = !d->ErrorText(d->m_ImageGenerator.Create(d->m_Context)); + d->m_ImageGenerator.GetMapOutputMode(ImageMode); + ImageMode.nXRes = xn::Resolution((XnResolution)XN_RES_VGA).GetXResolution(); + ImageMode.nYRes = xn::Resolution((XnResolution)XN_RES_VGA).GetYResolution(); + d->m_ConnectionCheck = !d->ErrorText(d->m_ImageGenerator.SetMapOutputMode(ImageMode)); + } + + // Camera registration + if ( d->m_DepthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) ) + { + if (d->m_UseIR) + { + d->m_ConnectionCheck = !d->ErrorText(d->m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_IRGenerator)); + } + else + { + d->m_ConnectionCheck = !d->ErrorText(d->m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_ImageGenerator)); + } + } + else + { + std::cout << "Alternative view point not supported by the depth generator..." << std::endl; + } + if (d->m_UseIR) + { + if ( d->m_IRGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) ) + { + d->m_ConnectionCheck = !d->ErrorText(d->m_IRGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_DepthGenerator)); + } + else + { + std::cout << "Alternative view point not supported by the depth generator..." << std::endl; + } + } + + // Mirror data + d->m_ConnectionCheck = d->ErrorText(d->m_Context.SetGlobalMirror(!d->m_Context.GetGlobalMirror())); + + // Start data generation + d->m_ConnectionCheck = d->ErrorText(d->m_Context.StartGeneratingAll()); + +// // Update the connected flag +// d->m_ConnectionCheck = true; + } + return d->m_ConnectionCheck; + } + + bool KinectController::CloseCameraConnection() + { + d->m_ConnectionCheck = !d->ErrorText(d->m_Context.StopGeneratingAll()); + return !d->m_ConnectionCheck; + } + + bool KinectController::UpdateCamera() + { + bool updateSuccessful = d->ErrorText(d->m_Context.WaitAndUpdateAll()); + xn::DepthMetaData DepthMD; + d->m_DepthGenerator.GetMetaData(DepthMD); + d->m_CaptureWidth = DepthMD.XRes(); + d->m_CaptureHeight = DepthMD.YRes(); + return updateSuccessful; + } + + // TODO flag image + void KinectController::GetDistances(float* distances) + { + xn::DepthMetaData DepthMD; + d->m_DepthGenerator.GetMetaData(DepthMD); + const XnDepthPixel* DepthData = DepthMD.Data(); + + for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) + { + distances[i] = DepthData[i]; + } + } + + void KinectController::GetRgb(unsigned char* rgb) + { + if (!d->m_UseIR) + { + xn::ImageMetaData ImageMD; + d->m_ImageGenerator.GetMetaData(ImageMD); + const XnRGB24Pixel* rgbPixelArray = ImageMD.RGB24Data(); + for (int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) + { + rgb[i*3] = rgbPixelArray[i].nRed; + rgb[i*3+1] = rgbPixelArray[i].nGreen; + rgb[i*3+2] = rgbPixelArray[i].nBlue; + } + } + } + + void KinectController::GetAllData(float* distances, float* amplitudes, unsigned char* rgb) + { + // get current distance data + xn::DepthMetaData DepthMD; + d->m_DepthGenerator.GetMetaData(DepthMD); + const XnDepthPixel* DepthData = DepthMD.Data(); + // IR data + xn::IRMetaData IRData; + const XnIRPixel* IRPixelData; + // Image data + xn::ImageMetaData ImageMD; + const XnRGB24Pixel* rgbPixelArray; + if (d->m_UseIR) + { + d->m_IRGenerator.GetMetaData(IRData); + IRPixelData = IRData.Data(); + } + else + { + // get current rgb data + d->m_ImageGenerator.GetMetaData(ImageMD); + rgbPixelArray = ImageMD.RGB24Data(); + } + + for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) + { + distances[i] = DepthData[i]; + if (d->m_UseIR) + { + amplitudes[i] = IRPixelData[i]; + } + else + { + rgb[i*3] = rgbPixelArray[i].nRed; + rgb[i*3+1] = rgbPixelArray[i].nGreen; + rgb[i*3+2] = rgbPixelArray[i].nBlue; + } + } + } + + void KinectController::GetAmplitudes( float* amplitudes ) + { + if (d->m_UseIR) + { + xn::IRMetaData IRData; + d->m_IRGenerator.GetMetaData(IRData); + const XnIRPixel* IRPixelData = IRData.Data(); + + for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) + { + amplitudes[i] = IRPixelData[i]; + } + } + } + + void KinectController::GetIntensities( float* intensities ) + { + + } + unsigned int KinectController::GetCaptureWidth() const + { + return d->m_CaptureWidth; + } + + unsigned int KinectController::GetCaptureHeight() const + { + return d->m_CaptureHeight; + } + + bool KinectController::GetUseIR() const + { + return d->m_UseIR; + } + void KinectController::SetUseIR(bool useIR) + { + if (d->m_UseIR!=useIR) + { + d->m_UseIR = useIR; + this->Modified(); + } + } +} diff --git a/Modules/ToFHardware/mitkKinectController.h b/Modules/ToFHardware/mitkKinectController.h new file mode 100644 index 0000000000..653912d291 --- /dev/null +++ b/Modules/ToFHardware/mitkKinectController.h @@ -0,0 +1,91 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef __mitkKinectController_h +#define __mitkKinectController_h + +#include "mitkToFHardwareExports.h" +#include "mitkCommon.h" +#include "mitkToFConfig.h" + +#include "itkObject.h" +#include "itkObjectFactory.h" + +namespace mitk +{ + /** + * @brief Interface to the Kinect camera + * + * + * @ingroup ToFHardware + */ + class MITK_TOFHARDWARE_EXPORT KinectController : public itk::Object + { + public: + + mitkClassMacro( KinectController , itk::Object ); + + itkNewMacro( Self ); + + unsigned int GetCaptureWidth() const; + unsigned int GetCaptureHeight() const; + bool GetUseIR() const; + + void SetUseIR(bool useIR); + + /*! + \brief opens a connection to the Kinect camera. + */ + virtual bool OpenCameraConnection(); + /*! + \brief closes the connection to the camera + */ + virtual bool CloseCameraConnection(); + /*! + \brief updates the camera. The update function of the hardware interface is called only when new data is available + */ + virtual bool UpdateCamera(); + /*! + \brief acquire new distance data from the Kinect camera + \param distances pointer to memory location where distances should be stored + */ + void GetDistances(float* distances); + void GetAmplitudes(float* amplitudes); + void GetIntensities(float* intensities); + /*! + \brief acquire new rgb data from the Kinect camera + \parama rgb pointer to memory location where rgb information should be stored + */ + void GetRgb(unsigned char* rgb); + /*! + \brief convenience method for faster access to distance and rgb data + \param distances pointer to memory location where distances should be stored + \param rgb pointer to memory location where rgb information should be stored + */ + void GetAllData(float* distances, float* amplitudes, unsigned char* rgb); + + protected: + + KinectController(); + + ~KinectController(); + + private: + class KinectControllerPrivate; + KinectControllerPrivate *d; + + }; +} //END mitk namespace +#endif diff --git a/Modules/ToFHardware/mitkKinectControllerStub.cpp b/Modules/ToFHardware/mitkKinectControllerStub.cpp new file mode 100644 index 0000000000..b10a4d69e9 --- /dev/null +++ b/Modules/ToFHardware/mitkKinectControllerStub.cpp @@ -0,0 +1,96 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include "mitkKinectController.h" + +namespace mitk +{ + KinectController::KinectController() + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + KinectController::~KinectController() + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + bool KinectController::OpenCameraConnection() + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return true; + } + + bool KinectController::CloseCameraConnection() + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return true; + } + + bool KinectController::UpdateCamera() + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return true; + } + + // TODO flag image + void KinectController::GetDistances(float* distances) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + void KinectController::GetRgb(unsigned char* rgb) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + void KinectController::GetAllData(float* distances, float* amplitudes, unsigned char* rgb) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + void KinectController::GetAmplitudes( float* amplitudes ) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + void KinectController::GetIntensities( float* intensities ) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } + + unsigned int KinectController::GetCaptureWidth() const + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return 0; + } + + unsigned int KinectController::GetCaptureHeight() const + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return 0; + } + + bool KinectController::GetUseIR() const + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + return true; + } + + void KinectController::SetUseIR(bool useIR) + { + MITK_WARN("ToF") << "Error: Kinect camera currently not available"; + } +} diff --git a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp b/Modules/ToFHardware/mitkKinectDevice.cpp similarity index 71% copy from Modules/ToFHardware/mitkToFCameraMESADevice.cpp copy to Modules/ToFHardware/mitkKinectDevice.cpp index 7ba8527722..c8f88e2326 100644 --- a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp +++ b/Modules/ToFHardware/mitkKinectDevice.cpp @@ -1,446 +1,424 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkToFCameraMESADevice.h" +#include "mitkKinectDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { - ToFCameraMESADevice::ToFCameraMESADevice() + KinectDevice::KinectDevice() { + m_Controller = mitk::KinectController::New(); } - ToFCameraMESADevice::~ToFCameraMESADevice() + KinectDevice::~KinectDevice() { } - bool ToFCameraMESADevice::ConnectCamera() + bool KinectDevice::ConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } + this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize]; + for (int i=0; im_MaxBufferSize; i++) + { + this->m_RGBDataBuffer[i] = new unsigned char[this->m_PixelNumber*3]; + } m_CameraConnected = true; } } return ok; } - bool ToFCameraMESADevice::DisconnectCamera() + bool KinectDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); // clean-up only if camera was connected if (m_CameraConnected) { delete [] m_IntensityArray; delete [] m_DistanceArray; delete [] m_AmplitudeArray; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; - } - delete[] this->m_DistanceDataBuffer; - for(int i=0; im_MaxBufferSize; i++) - { delete[] this->m_AmplitudeDataBuffer[i]; - } - delete[] this->m_AmplitudeDataBuffer; - for(int i=0; im_MaxBufferSize; i++) - { delete[] this->m_IntensityDataBuffer[i]; + delete[] this->m_RGBDataBuffer[i]; } + delete[] this->m_DistanceDataBuffer; + delete[] this->m_AmplitudeDataBuffer; delete[] this->m_IntensityDataBuffer; + delete[] this->m_RGBDataBuffer; m_CameraConnected = false; } } return ok; } - void ToFCameraMESADevice::StartCamera() + void KinectDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); - this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]); - this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]); - this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]); + this->m_Controller->GetAllData(this->m_DistanceDataBuffer[this->m_FreePos],this->m_AmplitudeDataBuffer[this->m_FreePos],this->m_RGBDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } - void ToFCameraMESADevice::StopCamera() + void KinectDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } - bool ToFCameraMESADevice::IsCameraActive() + bool KinectDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } - void ToFCameraMESADevice::UpdateCamera() + void KinectDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } - ITK_THREAD_RETURN_TYPE ToFCameraMESADevice::Acquire(void* pInfoStruct) + ITK_THREAD_RETURN_TYPE KinectDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } - ToFCameraMESADevice* toFCameraDevice = (ToFCameraMESADevice*)pInfo->UserData; + KinectDevice* toFCameraDevice = (KinectDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the image data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); - toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]); - toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]); - toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]); + toFCameraDevice->m_Controller->GetAllData(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + TODO Buffer Handling currently only works for buffer size 1 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { // buffer overflow //MITK_INFO << "Buffer overflow!! "; //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { //itksys::SystemTools::Delay(10); overflow = false; } /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + END TODO Buffer Handling currently only works for buffer size 1 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // void ToFCameraMESADevice::ResetBuffer(int bufferSize) + // void KinectDevice::ResetBuffer(int bufferSize) // { // this->m_BufferSize = bufferSize; // this->m_CurrentPos = -1; // this->m_FreePos = 0; // } - void ToFCameraMESADevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) + void KinectDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) /* this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); for (int i=0; im_CaptureHeight; i++) { - for (int j=0; jm_CaptureWidth; j++) - { - amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; - } + for (int j=0; jm_CaptureWidth; j++) + { + amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; + } } */ for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } - void ToFCameraMESADevice::GetIntensities(float* intensityArray, int& imageSequence) + void KinectDevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) Flip around y- axis (vertical axis) + // 1) copy the image buffer + // 2) Flip around y- axis (vertical axis) - /* - this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); - for (int i=0; im_CaptureHeight; i++) - { + /* + this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); + for (int i=0; im_CaptureHeight; i++) + { for (int j=0; jm_CaptureWidth; j++) { - intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; + intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; } - } - */ + } + */ for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } - void ToFCameraMESADevice::GetDistances(float* distanceArray, int& imageSequence) + void KinectDevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) /* this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); for (int i=0; im_CaptureHeight; i++) { - for (int j=0; jm_CaptureWidth; j++) - { - distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; - } + for (int j=0; jm_CaptureWidth; j++) + { + distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; + } } */ for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; // * 1000 } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } - void ToFCameraMESADevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence) + void KinectDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } // write image data to float arrays for (int i=0; im_PixelNumber; i++) { - distanceArray[i] = this->m_DistanceDataBuffer[pos][i] /* * 1000 */; + distanceArray[i] = this->m_DistanceDataBuffer[pos][i]; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; + rgbDataArray[i*3] = this->m_RGBDataBuffer[pos][i*3]; + rgbDataArray[i*3+1] = this->m_RGBDataBuffer[pos][i*3+1]; + rgbDataArray[i*3+2] = this->m_RGBDataBuffer[pos][i*3+2]; } - - - /* - this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray); - this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray); - this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray); - - int u, v; - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - u = i*this->m_CaptureWidth+j; - v = (i+1)*this->m_CaptureWidth-1-j; - distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in mm - //distanceArray[u] = this->m_DistanceArray[v]; // unit in meter - amplitudeArray[u] = this->m_AmplitudeArray[v]; - intensityArray[u] = this->m_IntensityArray[v]; - } - } - - memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); - */ } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } - ToFCameraMESAController::Pointer ToFCameraMESADevice::GetController() + KinectController::Pointer KinectDevice::GetController() { return this->m_Controller; } - void ToFCameraMESADevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) + void KinectDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); - if (strcmp(propertyKey, "ModulationFrequency") == 0) + if (strcmp(propertyKey, "RGB") == 0) { - int modulationFrequency = 0; - GetIntProperty(propertyValue, modulationFrequency); - m_Controller->SetModulationFrequency(modulationFrequency); + bool rgb = false; + GetBoolProperty(propertyKey, rgb); + m_Controller->SetUseIR(!rgb); } - else if (strcmp(propertyKey, "IntegrationTime") == 0) + else if (strcmp(propertyKey, "IR") == 0) { - int integrationTime = 0; - GetIntProperty(propertyValue, integrationTime); - m_Controller->SetIntegrationTime(integrationTime); + bool ir = false; + GetBoolProperty(propertyKey, ir); + m_Controller->SetUseIR(ir); } } } diff --git a/Modules/ToFHardware/mitkToFCameraMESADevice.h b/Modules/ToFHardware/mitkKinectDevice.h similarity index 79% copy from Modules/ToFHardware/mitkToFCameraMESADevice.h copy to Modules/ToFHardware/mitkKinectDevice.h index 2f48778903..31a5960f3d 100644 --- a/Modules/ToFHardware/mitkToFCameraMESADevice.h +++ b/Modules/ToFHardware/mitkKinectDevice.h @@ -1,146 +1,147 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkToFCameraMESADevice_h -#define __mitkToFCameraMESADevice_h +#ifndef __mitkKinectDevice_h +#define __mitkKinectDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" -#include "mitkToFCameraMESAController.h" +#include "mitkKinectController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of MESA ToF devices. - * ToFCameraMESADevice internally holds an instance of ToFCameraMESAController and starts a thread + * KinectDevice internally holds an instance of KinectController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ - class MITK_TOFHARDWARE_EXPORT ToFCameraMESADevice : public ToFCameraDevice + class MITK_TOFHARDWARE_EXPORT KinectDevice : public ToFCameraDevice { public: - mitkClassMacro( ToFCameraMESADevice , ToFCameraDevice ); + mitkClassMacro( KinectDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence); -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /*! -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); + // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated + // /*! + // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes + // \param bufferSize buffer size the buffer should be reset to + // */ + // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ - ToFCameraMESAController::Pointer GetController(); + KinectController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: - ToFCameraMESADevice(); + KinectDevice(); - ~ToFCameraMESADevice(); + ~KinectDevice(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); - ToFCameraMESAController::Pointer m_Controller; ///< corresponding CameraController + KinectController::Pointer m_Controller; ///< corresponding CameraController float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images + unsigned char** m_RGBDataBuffer; ///< buffer holding the last RGB image private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraDevice.cpp b/Modules/ToFHardware/mitkToFCameraDevice.cpp index 4c8ed4de92..c8f30aa753 100644 --- a/Modules/ToFHardware/mitkToFCameraDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraDevice.cpp @@ -1,135 +1,134 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraDevice.h" namespace mitk { ToFCameraDevice::ToFCameraDevice():m_BufferSize(1),m_MaxBufferSize(100),m_CurrentPos(-1),m_FreePos(0), m_CaptureWidth(204),m_CaptureHeight(204),m_PixelNumber(41616),m_SourceDataSize(0), m_ThreadID(0),m_CameraActive(false),m_CameraConnected(false),m_ImageSequence(0) { this->m_AmplitudeArray = NULL; this->m_IntensityArray = NULL; this->m_DistanceArray = NULL; this->m_PropertyList = mitk::PropertyList::New(); this->m_MultiThreader = itk::MultiThreader::New(); this->m_ImageMutex = itk::FastMutexLock::New(); this->m_CameraActiveMutex = itk::FastMutexLock::New(); } ToFCameraDevice::~ToFCameraDevice() { - CleanupPixelArrays(); } void ToFCameraDevice::SetBoolProperty( const char* propertyKey, bool boolValue ) { SetProperty(propertyKey, mitk::BoolProperty::New(boolValue)); } void ToFCameraDevice::SetIntProperty( const char* propertyKey, int intValue ) { SetProperty(propertyKey, mitk::IntProperty::New(intValue)); } void ToFCameraDevice::SetFloatProperty( const char* propertyKey, float floatValue ) { SetProperty(propertyKey, mitk::FloatProperty::New(floatValue)); } void ToFCameraDevice::SetStringProperty( const char* propertyKey, const char* stringValue ) { SetProperty(propertyKey, mitk::StringProperty::New(stringValue)); } void ToFCameraDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { this->m_PropertyList->SetProperty(propertyKey, propertyValue); } BaseProperty* ToFCameraDevice::GetProperty(const char *propertyKey) { return this->m_PropertyList->GetProperty(propertyKey); } - bool ToFCameraDevice::GetBoolProperty(BaseProperty* propertyValue, bool& boolValue) + bool ToFCameraDevice::GetBoolProperty(const char *propertyKey, bool& boolValue) { - mitk::BoolProperty::Pointer boolprop = dynamic_cast(propertyValue); + mitk::BoolProperty::Pointer boolprop = dynamic_cast(this->GetProperty(propertyKey)); if(boolprop.IsNull()) return false; boolValue = boolprop->GetValue(); return true; } - bool ToFCameraDevice::GetStringProperty(BaseProperty* propertyValue, std::string& string) + bool ToFCameraDevice::GetStringProperty(const char *propertyKey, std::string& string) { - mitk::StringProperty::Pointer stringProp = dynamic_cast(propertyValue); + mitk::StringProperty::Pointer stringProp = dynamic_cast(this->GetProperty(propertyKey)); if(stringProp.IsNull()) { return false; } else { string = stringProp->GetValue(); return true; } } - bool ToFCameraDevice::GetIntProperty(BaseProperty* propertyValue, int& integer) + bool ToFCameraDevice::GetIntProperty(const char *propertyKey, int& integer) { - mitk::IntProperty::Pointer intProp = dynamic_cast(propertyValue); + mitk::IntProperty::Pointer intProp = dynamic_cast(this->GetProperty(propertyKey)); if(intProp.IsNull()) { return false; } else { integer = intProp->GetValue(); return true; } } void ToFCameraDevice::CleanupPixelArrays() { if (m_IntensityArray) { delete [] m_IntensityArray; } if (m_DistanceArray) { delete [] m_DistanceArray; } if (m_AmplitudeArray) { delete [] m_AmplitudeArray; } } void ToFCameraDevice::AllocatePixelArrays() { // free memory if it was already allocated CleanupPixelArrays(); // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} } } diff --git a/Modules/ToFHardware/mitkToFCameraDevice.h b/Modules/ToFHardware/mitkToFCameraDevice.h index 115b237c92..13ccdc7160 100644 --- a/Modules/ToFHardware/mitkToFCameraDevice.h +++ b/Modules/ToFHardware/mitkToFCameraDevice.h @@ -1,215 +1,215 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraDevice_h #define __mitkToFCameraDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkStringProperty.h" #include "mitkProperties.h" #include "mitkPropertyList.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Virtual interface and base class for all Time-of-Flight devices. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraDevice : public itk::Object { public: mitkClassMacro(ToFCameraDevice, itk::Object); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera() = 0; /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera() = 0; /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera() = 0; /*! \brief stops the continuous updating of the camera */ virtual void StopCamera() = 0; /*! \brief returns true if the camera is connected and started */ virtual bool IsCameraActive() = 0; /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera() = 0; /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence) = 0; /*! \brief gets the intensity data from the ToF camera as a greyscale image \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence) = 0; /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence) = 0; /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ - virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence) = 0; + virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL) = 0; // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // /*! // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes // \param bufferSize buffer size the buffer should be reset to // */ // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief get the currently set capture width \return capture width */ itkGetMacro(CaptureWidth, int); /*! \brief get the currently set capture height \return capture height */ itkGetMacro(CaptureHeight, int); /*! \brief get the currently set source data size \return source data size */ itkGetMacro(SourceDataSize, int); /*! \brief get the currently set buffer size \return buffer size */ itkGetMacro(BufferSize, int); /*! \brief get the currently set max buffer size \return max buffer size */ itkGetMacro(MaxBufferSize, int); /*! \brief set a bool property in the property list */ void SetBoolProperty( const char* propertyKey, bool boolValue ); /*! \brief set an int property in the property list */ void SetIntProperty( const char* propertyKey, int intValue ); /*! \brief set a float property in the property list */ void SetFloatProperty( const char* propertyKey, float floatValue ); /*! \brief set a string property in the property list */ void SetStringProperty( const char* propertyKey, const char* stringValue ); /*! \brief set a BaseProperty property in the property list */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); /*! \brief get a BaseProperty from the property list */ virtual BaseProperty* GetProperty( const char *propertyKey ); /*! \brief get a bool from the property list */ - static bool GetBoolProperty(BaseProperty* propertyValue, bool& boolValue); + bool GetBoolProperty(const char *propertyKey, bool& boolValue); /*! \brief get a string from the property list */ - static bool GetStringProperty(BaseProperty* propertyValue, std::string& string); + bool GetStringProperty(const char *propertyKey, std::string& string); /*! \brief get an int from the property list */ - static bool GetIntProperty(BaseProperty* propertyValue, int& integer); + bool GetIntProperty(const char *propertyKey, int& integer); protected: ToFCameraDevice(); ~ToFCameraDevice(); /*! \brief method for allocating memory for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void AllocatePixelArrays(); /*! \brief method for cleanup memory allocated for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void CleanupPixelArrays(); float* m_IntensityArray; ///< float array holding the intensity image float* m_DistanceArray; ///< float array holding the distance image float* m_AmplitudeArray; ///< float array holding the amplitude image int m_BufferSize; ///< buffer size of the image buffer needed for loss-less acquisition of range data int m_MaxBufferSize; ///< maximal buffer size needed for initialization of data arrays. Default value is 100. int m_CurrentPos; ///< current position in the buffer which will be retrieved by the Get methods int m_FreePos; ///< current position in the buffer which will be filled with data acquired from the hardware int m_CaptureWidth; ///< width of the range image (x dimension) int m_CaptureHeight; ///< height of the range image (y dimension) int m_PixelNumber; ///< number of pixels in the range image (m_CaptureWidth*m_CaptureHeight) int m_SourceDataSize; ///< size of the PMD source data itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the range camera itk::FastMutexLock::Pointer m_CameraActiveMutex; ///< mutex for the cameraActive flag int m_ThreadID; ///< ID of the started thread bool m_CameraActive; ///< flag indicating if the camera is currently active or not. Caution: thread safe access only! bool m_CameraConnected; ///< flag indicating if the camera is successfully connected or not. Caution: thread safe access only! int m_ImageSequence; ///< counter for acquired images PropertyList::Pointer m_PropertyList; ///< a list of the corresponding properties private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp b/Modules/ToFHardware/mitkToFCameraMESADevice.cpp index 7ba8527722..6d7f87bbac 100644 --- a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraMESADevice.cpp @@ -1,446 +1,446 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMESADevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraMESADevice::ToFCameraMESADevice() { } ToFCameraMESADevice::~ToFCameraMESADevice() { } bool ToFCameraMESADevice::ConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } m_CameraConnected = true; } } return ok; } bool ToFCameraMESADevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); // clean-up only if camera was connected if (m_CameraConnected) { delete [] m_IntensityArray; delete [] m_DistanceArray; delete [] m_AmplitudeArray; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_AmplitudeDataBuffer[i]; } delete[] this->m_AmplitudeDataBuffer; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_IntensityDataBuffer[i]; } delete[] this->m_IntensityDataBuffer; m_CameraConnected = false; } } return ok; } void ToFCameraMESADevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]); this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]); this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraMESADevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool ToFCameraMESADevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraMESADevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraMESADevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraMESADevice* toFCameraDevice = (ToFCameraMESADevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the image data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { // buffer overflow //MITK_INFO << "Buffer overflow!! "; //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { //itksys::SystemTools::Delay(10); overflow = false; } /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! END TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // void ToFCameraMESADevice::ResetBuffer(int bufferSize) // { // this->m_BufferSize = bufferSize; // this->m_CurrentPos = -1; // this->m_FreePos = 0; // } void ToFCameraMESADevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) /* this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; } } */ for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) /* this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; } } */ for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) /* this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; } } */ for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; // * 1000 } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence) + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } // write image data to float arrays for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[pos][i] /* * 1000 */; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; } /* this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray); this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray); this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray); int u, v; for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { u = i*this->m_CaptureWidth+j; v = (i+1)*this->m_CaptureWidth-1-j; distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in mm //distanceArray[u] = this->m_DistanceArray[v]; // unit in meter amplitudeArray[u] = this->m_AmplitudeArray[v]; intensityArray[u] = this->m_IntensityArray[v]; } } memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); */ } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } ToFCameraMESAController::Pointer ToFCameraMESADevice::GetController() { return this->m_Controller; } void ToFCameraMESADevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; - GetIntProperty(propertyValue, modulationFrequency); + GetIntProperty(propertyKey, modulationFrequency); m_Controller->SetModulationFrequency(modulationFrequency); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; - GetIntProperty(propertyValue, integrationTime); + GetIntProperty(propertyKey, integrationTime); m_Controller->SetIntegrationTime(integrationTime); } } } diff --git a/Modules/ToFHardware/mitkToFCameraMESADevice.h b/Modules/ToFHardware/mitkToFCameraMESADevice.h index 2f48778903..7a85b18717 100644 --- a/Modules/ToFHardware/mitkToFCameraMESADevice.h +++ b/Modules/ToFHardware/mitkToFCameraMESADevice.h @@ -1,146 +1,146 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMESADevice_h #define __mitkToFCameraMESADevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraMESAController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of MESA ToF devices. * ToFCameraMESADevice internally holds an instance of ToFCameraMESAController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraMESADevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraMESADevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence); + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // /*! // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes // \param bufferSize buffer size the buffer should be reset to // */ // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ ToFCameraMESAController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraMESADevice(); ~ToFCameraMESADevice(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); ToFCameraMESAController::Pointer m_Controller; ///< corresponding CameraController float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraMESASR4000Device.cpp b/Modules/ToFHardware/mitkToFCameraMESASR4000Device.cpp index d02587ddc3..60ffbeab5d 100644 --- a/Modules/ToFHardware/mitkToFCameraMESASR4000Device.cpp +++ b/Modules/ToFHardware/mitkToFCameraMESASR4000Device.cpp @@ -1,69 +1,69 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMESASR4000Device.h" #include "mitkToFCameraMESASR4000Controller.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" namespace mitk { ToFCameraMESASR4000Device::ToFCameraMESASR4000Device() { m_Controller = ToFCameraMESASR4000Controller::New(); } ToFCameraMESASR4000Device::~ToFCameraMESASR4000Device() { } void ToFCameraMESASR4000Device::SetRegionOfInterest(unsigned int leftUpperCornerX, unsigned int leftUpperCornerY, unsigned int width, unsigned int height) { //if (m_Controller.IsNotNull()) //{ // dynamic_cast(m_Controller.GetPointer())->SetRegionOfInterest(leftUpperCornerX,leftUpperCornerY,width,height); //} } void ToFCameraMESASR4000Device::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraMESADevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraMESASR4000Controller::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); bool boolValue = false; - GetBoolProperty(propertyValue, boolValue); + GetBoolProperty(propertyKey, boolValue); if (strcmp(propertyKey, "SetFPN") == 0) { myController->SetFPN(boolValue); } else if (strcmp(propertyKey, "SetConvGray") == 0) { myController->SetConvGray(boolValue); } else if (strcmp(propertyKey, "SetMedian") == 0) { myController->SetMedian(boolValue); } else if (strcmp(propertyKey, "SetANF") == 0) { myController->SetANF(boolValue); } } } diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp index 26dfa8fb73..0046700601 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp @@ -1,344 +1,396 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include // mitk includes #include "mitkItkImageFileReader.h" #include "mitkPicFileReader.h" #include namespace mitk { ToFCameraMITKPlayerController::ToFCameraMITKPlayerController() : m_PixelNumber(0), m_NumberOfBytes(0), m_CaptureWidth(0), m_CaptureHeight(0), m_ConnectionCheck(false), m_InputFileName(""), m_Extension(""), m_ToFImageType(ToFImageType3D), m_DistanceImage(0), m_AmplitudeImage(0), m_IntensityImage(0), + m_RGBImage(0), m_DistanceInfile(NULL), m_AmplitudeInfile(NULL), m_IntensityInfile(NULL), + m_RGBInfile(NULL), m_IntensityArray(NULL), m_DistanceArray(NULL), m_AmplitudeArray(NULL), + m_RGBArray(NULL), m_DistanceImageFileName(""), m_AmplitudeImageFileName(""), m_IntensityImageFileName(""), + m_RGBImageFileName(""), m_PixelStartInFile(0), m_CurrentFrame(-1), m_NumOfFrames(0) { - m_ImageStatus = std::vector(3,true); + m_ImageStatus = std::vector(4,true); } ToFCameraMITKPlayerController::~ToFCameraMITKPlayerController() { this->CleanUp(); } void ToFCameraMITKPlayerController::CleanUp() { if(m_DistanceImage.IsNotNull()) { m_DistanceImage->ReleaseData(); m_DistanceImage = NULL; } if(m_AmplitudeImage.IsNotNull()) { m_AmplitudeImage->ReleaseData(); m_AmplitudeImage = NULL; } if(m_IntensityImage.IsNotNull()) { m_IntensityImage->ReleaseData(); m_IntensityImage = NULL; } + if(m_RGBImage.IsNotNull()) + { + m_RGBImage->ReleaseData(); + m_RGBImage = NULL; + } delete[] this->m_DistanceArray; this->m_DistanceArray = NULL; delete[] this->m_AmplitudeArray; this->m_AmplitudeArray = NULL; delete[] this->m_IntensityArray; this->m_IntensityArray = NULL; + delete[] this->m_RGBArray; + this->m_RGBArray = NULL; } bool ToFCameraMITKPlayerController::CheckCurrentFileType() { if(!this->m_DistanceImageFileName.empty()) { if(ItkImageFileReader::CanReadFile(m_DistanceImageFileName,"",".nrrd")) { m_Extension = ".nrrd"; return true; } else if (PicFileReader::CanReadFile(m_DistanceImageFileName,"",".pic")) { m_Extension = ".pic"; return true; } } if(!this->m_AmplitudeImageFileName.empty()) { if(ItkImageFileReader::CanReadFile(m_AmplitudeImageFileName,"",".nrrd")) { m_Extension = ".nrrd"; return true; } else if (PicFileReader::CanReadFile(m_AmplitudeImageFileName,"",".pic")) { m_Extension = ".pic"; return true; } } if(!this->m_IntensityImageFileName.empty()) { if(ItkImageFileReader::CanReadFile(m_IntensityImageFileName,"",".nrrd")) { m_Extension = ".nrrd"; return true; } else if (PicFileReader::CanReadFile(m_IntensityImageFileName,"",".pic")) { m_Extension = ".pic"; return true; } } + if(!this->m_RGBImageFileName.empty()) + { + if(ItkImageFileReader::CanReadFile(m_RGBImageFileName,"",".nrrd")) + { + m_Extension = ".nrrd"; + return true; + } + else if (PicFileReader::CanReadFile(m_RGBImageFileName,"",".pic")) + { + m_Extension = ".pic"; + return true; + } + } return false; } bool ToFCameraMITKPlayerController::OpenCameraConnection() { if(!this->m_ConnectionCheck) { try { // Check for file type, only .nrrd and .pic files are supported! if( this->CheckCurrentFileType()) { if(m_Extension == ".nrrd") { this->OpenNrrdImageFile(this->m_DistanceImageFileName, m_DistanceImage); this->OpenNrrdImageFile(this->m_AmplitudeImageFileName, m_AmplitudeImage); this->OpenNrrdImageFile(this->m_IntensityImageFileName, m_IntensityImage); + this->OpenNrrdImageFile(this->m_RGBImageFileName, m_RGBImage); } else if(m_Extension == ".pic") { this->OpenPicImageFile(this->m_DistanceImageFileName, m_DistanceImage); this->OpenPicImageFile(this->m_AmplitudeImageFileName, m_AmplitudeImage); this->OpenPicImageFile(this->m_IntensityImageFileName, m_IntensityImage); + this->OpenPicImageFile(this->m_RGBImageFileName, m_RGBImage); } } else { throw std::logic_error("Please check image type, currently only .nrrd files are supported (.pic files are deprecated!)"); } // check if the opened files contained data if(m_DistanceImage.IsNull()) { m_ImageStatus.at(0) = false; } if(m_AmplitudeImage.IsNull()) { m_ImageStatus.at(1) = false; } if(m_IntensityImage.IsNull()) { m_ImageStatus.at(2) = false; } - + if(m_RGBImage.IsNull()) + { + m_ImageStatus.at(3) = false; + } + // Check for dimension type mitk::Image::Pointer infoImage = NULL; if(m_ImageStatus.at(0)) { infoImage = m_DistanceImage; } else if (m_ImageStatus.at(1)) { infoImage = m_AmplitudeImage; } else if(m_ImageStatus.at(2)) { infoImage = m_IntensityImage; } + else if(m_ImageStatus.at(3)) + { + infoImage = m_RGBImage; + } if (infoImage->GetDimension() == 2) this->m_ToFImageType = ToFImageType2DPlusT; else if (infoImage->GetDimension() == 3) this->m_ToFImageType = ToFImageType3D; else if (infoImage->GetDimension() == 4) this->m_ToFImageType = ToFImageType2DPlusT; else throw std::logic_error("Error opening ToF data file: Invalid dimension."); this->m_CaptureWidth = infoImage->GetDimension(0); this->m_CaptureHeight = infoImage->GetDimension(1); this->m_PixelNumber = this->m_CaptureWidth*this->m_CaptureHeight; this->m_NumberOfBytes = this->m_PixelNumber * sizeof(float); if (this->m_ToFImageType == ToFImageType2DPlusT) { this->m_NumOfFrames = infoImage->GetDimension(3); } else { this->m_NumOfFrames = infoImage->GetDimension(2); } // allocate buffer this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} + this->m_RGBArray = new unsigned char[this->m_PixelNumber*3]; + for(int i=0; im_PixelNumber*3; i++) {this->m_RGBArray[i]=0.0;} MITK_INFO << "NumOfFrames: " << this->m_NumOfFrames; this->m_ConnectionCheck = true; return this->m_ConnectionCheck; } catch(std::exception& e) { MITK_ERROR << "Error opening ToF data file " << this->m_InputFileName << " " << e.what(); throw std::logic_error("Error opening ToF data file"); return false; } } else return this->m_ConnectionCheck; } void ToFCameraMITKPlayerController::OpenNrrdImageFile( const std::string outfileName, Image::Pointer &image) { if(!outfileName.empty()) { if(image.IsNotNull()) { image->ReleaseData(); image = NULL; } ItkImageFileReader::Pointer nrrdReader = ItkImageFileReader::New(); nrrdReader->SetFileName(outfileName); nrrdReader->Update(); image = nrrdReader->GetOutput()->Clone(); } else { MITK_ERROR << "Error opening ToF data file " << outfileName; } } void ToFCameraMITKPlayerController::OpenPicImageFile( const std::string outfileName, Image::Pointer &image) { if(!outfileName.empty()) { if(image.IsNotNull()) { image->ReleaseData(); image = NULL; } PicFileReader::Pointer picReader = PicFileReader::New(); picReader->SetFileName(outfileName); picReader->Update(); image = picReader->GetOutput()->Clone(); } else { MITK_ERROR << "Error opening ToF data file " << outfileName; } } bool ToFCameraMITKPlayerController::CloseCameraConnection() { if (this->m_ConnectionCheck) { this->CleanUp(); this->m_ConnectionCheck = false; return true; } return false; } void ToFCameraMITKPlayerController::UpdateCamera() { this->m_CurrentFrame++; if(this->m_CurrentFrame >= this->m_NumOfFrames) { this->m_CurrentFrame = 0; } if(this->m_ImageStatus.at(0)) { this->AccessData(this->m_CurrentFrame, this->m_DistanceImage, this->m_DistanceArray); } if(this->m_ImageStatus.at(1)) { this->AccessData(this->m_CurrentFrame, this->m_AmplitudeImage, this->m_AmplitudeArray); } if(this->m_ImageStatus.at(2)) { this->AccessData(this->m_CurrentFrame, this->m_IntensityImage, this->m_IntensityArray); } + if(this->m_ImageStatus.at(3)) + { + if(!this->m_ToFImageType) + { + memcpy(m_RGBArray, m_RGBImage->GetSliceData(m_CurrentFrame)->GetData(),m_PixelNumber * sizeof(unsigned char)*3 ); + } + else if(this->m_ToFImageType) + { + memcpy(m_RGBArray, m_RGBImage->GetVolumeData(m_CurrentFrame)->GetData(), m_PixelNumber * sizeof(unsigned char)*3); + } + } itksys::SystemTools::Delay(50); } void ToFCameraMITKPlayerController::AccessData(int frame, Image::Pointer image, float* &data) { if(!this->m_ToFImageType) { memcpy(data, image->GetSliceData(frame)->GetData(),this->m_NumberOfBytes ); } else if(this->m_ToFImageType) { memcpy(data, image->GetVolumeData(frame)->GetData(), this->m_NumberOfBytes); } } void ToFCameraMITKPlayerController::GetAmplitudes(float* amplitudeArray) { memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_NumberOfBytes); } void ToFCameraMITKPlayerController::GetIntensities(float* intensityArray) { memcpy(intensityArray, this->m_IntensityArray, this->m_NumberOfBytes); } void ToFCameraMITKPlayerController::GetDistances(float* distanceArray) { memcpy(distanceArray, this->m_DistanceArray, this->m_NumberOfBytes); } + void ToFCameraMITKPlayerController::GetRgb(unsigned char* rgbArray) + { + memcpy(rgbArray, this->m_RGBArray, m_PixelNumber * sizeof(unsigned char)*3); + } + void ToFCameraMITKPlayerController::SetInputFileName(std::string inputFileName) { this->m_InputFileName = inputFileName; } } diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.h b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.h index 78a577c77d..4fd8443f38 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.h +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.h @@ -1,132 +1,142 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMITKPlayerController_h #define __mitkToFCameraMITKPlayerController_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkFileReader.h" #include "mitkImage.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /** * @brief Controller for playing ToF images saved in MITK (.pic) format * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraMITKPlayerController : public itk::Object { public: mitkClassMacro( ToFCameraMITKPlayerController , itk::Object ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera \return Returns 'true' if connection could be established and 'false' otherwise */ virtual bool OpenCameraConnection(); /*! \brief closes the connection to the camera \return Returns 'true' if connection could be closed (i.e. only if a connection was established before) and 'false' otherwise */ virtual bool CloseCameraConnection(); /*! \brief gets the current amplitude frame from the input These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value */ virtual void GetAmplitudes(float* amplitudeArray); /*! \brief gets the current intensity frame from the input as a greyscale image */ virtual void GetIntensities(float* intensityArray); /*! \brief gets the current distance frame from the inpug measuring the distance between the camera and the different object points in millimeters */ virtual void GetDistances(float* distanceArray); /*! + \brief gets the current RGB frame from the input if available + */ + virtual void GetRgb(unsigned char* rgbArray); + /*! \brief updates the current image frames from input */ virtual void UpdateCamera(); virtual void SetInputFileName(std::string inputFileName); itkGetMacro(CaptureWidth, int); itkGetMacro(CaptureHeight, int); itkGetMacro( DistanceImageFileName, std::string ); itkGetMacro( AmplitudeImageFileName, std::string ); itkGetMacro( IntensityImageFileName, std::string ); + itkGetMacro( RGBImageFileName, std::string ); itkSetMacro( DistanceImageFileName, std::string ); itkSetMacro( AmplitudeImageFileName, std::string ); itkSetMacro( IntensityImageFileName, std::string ); + itkSetMacro( RGBImageFileName, std::string ); enum ToFImageType{ ToFImageType3D, ToFImageType2DPlusT }; protected: ToFCameraMITKPlayerController(); ~ToFCameraMITKPlayerController(); int m_PixelNumber; ///< holds the number of pixels contained in the image int m_NumberOfBytes; ///< holds the number of bytes contained in the image int m_CaptureWidth; ///< holds the width of the image int m_CaptureHeight; ///< holds the height of the image bool m_ConnectionCheck; ///< flag showing whether the camera is connected (true) or not (false) std::string m_InputFileName; std::string m_Extension; ToFImageType m_ToFImageType; ///< type of the ToF image to be played: 3D Volume (ToFImageType3D), temporal 2D image stack (ToFImageType2DPlusT) Image::Pointer m_DistanceImage; Image::Pointer m_AmplitudeImage; Image::Pointer m_IntensityImage; + Image::Pointer m_RGBImage; std::vector m_ImageStatus; FILE* m_DistanceInfile; ///< file holding the distance data FILE* m_AmplitudeInfile; ///< file holding the amplitude data FILE* m_IntensityInfile; ///< file holding the intensity data + FILE* m_RGBInfile; ///< file holding the rgb data float* m_IntensityArray; ///< member holding the current intensity frame float* m_DistanceArray; ///< member holding the current distance frame float* m_AmplitudeArray; ///< member holding the current amplitude frame + unsigned char* m_RGBArray; ///< member holding the current rgb frame std::string m_DistanceImageFileName; ///< file name of the distance image to be played std::string m_AmplitudeImageFileName; ///< file name of the amplitude image to be played std::string m_IntensityImageFileName; ///< file name of the intensity image to be played + std::string m_RGBImageFileName; ///< file name of the rgb image to be played long m_PixelStartInFile; int m_CurrentFrame; int m_NumOfFrames; private: //void OpenPicFileToData(FILE** outfile, const char *outfileName); void AccessData(int frame, Image::Pointer image, float* &data); bool CheckCurrentFileType(); void OpenNrrdImageFile( const std::string outfileName, Image::Pointer &image); void OpenPicImageFile( const std::string outfileName, Image::Pointer &image); void CleanUp(); }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp index ed4ad55ba9..b8b77c3344 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp @@ -1,371 +1,410 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMITKPlayerDevice.h" #include "mitkToFCameraMITKPlayerController.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraMITKPlayerDevice::ToFCameraMITKPlayerDevice() : - m_DistanceDataBuffer(NULL), m_AmplitudeDataBuffer(NULL), m_IntensityDataBuffer(NULL) + m_DistanceDataBuffer(NULL), m_AmplitudeDataBuffer(NULL), m_IntensityDataBuffer(NULL), m_RGBDataBuffer(NULL) { m_Controller = ToFCameraMITKPlayerController::New(); } ToFCameraMITKPlayerDevice::~ToFCameraMITKPlayerDevice() { DisconnectCamera(); CleanUpDataBuffers(); } bool ToFCameraMITKPlayerDevice::ConnectCamera() { bool ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; AllocatePixelArrays(); AllocateDataBuffers(); m_CameraConnected = true; } return ok; } bool ToFCameraMITKPlayerDevice::DisconnectCamera() { bool ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } return ok; } void ToFCameraMITKPlayerDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]); this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]); this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]); + this->m_Controller->GetRgb(this->m_RGBDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraMITKPlayerDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(100); } bool ToFCameraMITKPlayerDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraMITKPlayerDevice::UpdateCamera() { m_Controller->UpdateCamera(); } ITK_THREAD_RETURN_TYPE ToFCameraMITKPlayerDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraMITKPlayerDevice* toFCameraDevice = (ToFCameraMITKPlayerDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); int n = 100; double t1, t2; t1 = realTimeClock->GetCurrentStamp(); bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get image data from controller and write it to the according buffer toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]); + toFCameraDevice->m_Controller->GetRgb(toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->Modified(); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { // buffer overflow //MITK_INFO << "Buffer overflow!! "; //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } toFCameraDevice->m_ImageMutex->Unlock(); if (overflow) { //itksys::SystemTools::Delay(10); overflow = false; } /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! END TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // void ToFCameraMITKPlayerDevice::ResetBuffer(int bufferSize) // { // this->m_BufferSize = bufferSize; // this->m_CurrentPos = -1; // this->m_FreePos = 0; // } void ToFCameraMITKPlayerDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); /*!!!!!!!!!!!!!!!!!!!!!! TODO Buffer handling??? !!!!!!!!!!!!!!!!!!!!!!!!*/ // write amplitude image data to float array for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); /*!!!!!!!!!!!!!!!!!!!!!! TODO Buffer handling??? !!!!!!!!!!!!!!!!!!!!!!!!*/ // write intensity image data to float array for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); /*!!!!!!!!!!!!!!!!!!!!!! TODO Buffer handling??? !!!!!!!!!!!!!!!!!!!!!!!!*/ // write distance image data to float array for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } + void ToFCameraMITKPlayerDevice::GetRgb(unsigned char* rgbArray, int& imageSequence) + { + m_ImageMutex->Lock(); + /*!!!!!!!!!!!!!!!!!!!!!! + TODO Buffer handling??? + !!!!!!!!!!!!!!!!!!!!!!!!*/ + // write intensity image data to unsigned char array + for (int i=0; im_PixelNumber*3; i++) + { + rgbArray[i] = this->m_RGBDataBuffer[this->m_CurrentPos][i]; + } + imageSequence = this->m_ImageSequence; + m_ImageMutex->Unlock(); + } + void ToFCameraMITKPlayerDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* /*sourceDataArray*/, - int requiredImageSequence, int& capturedImageSequence) + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { /*!!!!!!!!!!!!!!!!!!!!!! TODO Document this method! !!!!!!!!!!!!!!!!!!!!!!!!*/ m_ImageMutex->Lock(); //check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } - if(this->m_DistanceDataBuffer&&this->m_AmplitudeDataBuffer&&this->m_IntensityDataBuffer) + if(this->m_DistanceDataBuffer&&this->m_AmplitudeDataBuffer&&this->m_IntensityDataBuffer&&this->m_RGBDataBuffer) { // write image data to float arrays for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[pos][i]; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; + rgbDataArray[i] = this->m_RGBDataBuffer[pos][i]; + } + for (int j=this->m_PixelNumber; jm_PixelNumber*3; j++) + { + rgbDataArray[j] = this->m_RGBDataBuffer[pos][j]; } } m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::SetInputFileName(std::string inputFileName) { this->m_InputFileName = inputFileName; this->m_Controller->SetInputFileName(inputFileName); } void ToFCameraMITKPlayerDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraMITKPlayerController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); std::string strValue; - GetStringProperty(propertyValue, strValue); + GetStringProperty(propertyKey, strValue); if (strcmp(propertyKey, "DistanceImageFileName") == 0) { myController->SetDistanceImageFileName(strValue); } else if (strcmp(propertyKey, "AmplitudeImageFileName") == 0) { myController->SetAmplitudeImageFileName(strValue); } else if (strcmp(propertyKey, "IntensityImageFileName") == 0) { myController->SetIntensityImageFileName(strValue); } + else if (strcmp(propertyKey, "RGBImageFileName") == 0) + { + myController->SetRGBImageFileName(strValue); + } } void ToFCameraMITKPlayerDevice::CleanUpDataBuffers() { if (m_DistanceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; } if (m_AmplitudeDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_AmplitudeDataBuffer[i]; } delete[] this->m_AmplitudeDataBuffer; } if (m_IntensityDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_IntensityDataBuffer[i]; } delete[] this->m_IntensityDataBuffer; } + if (m_RGBDataBuffer) + { + for(int i=0; im_MaxBufferSize; i++) + { + delete[] this->m_RGBDataBuffer[i]; + } + delete[] this->m_RGBDataBuffer; + } } void ToFCameraMITKPlayerDevice::AllocateDataBuffers() { // free memory if it was already allocated this->CleanUpDataBuffers(); // allocate buffers this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } + this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize]; + for(int i=0; im_MaxBufferSize; i++) + { + this->m_RGBDataBuffer[i] = new unsigned char[this->m_PixelNumber*3]; + } } } diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h index 6645d52f71..b02392795c 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h @@ -1,147 +1,154 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMITKPlayerDevice_h #define __mitkToFCameraMITKPlayerDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraMITKPlayerController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Device class representing a player for MITK-ToF images. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraMITKPlayerDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraMITKPlayerDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! + \brief gets the rgb data from the ToF camera. Caution! The user is responsible for allocating and deleting the images. + \param rgbArray contains the returned rgb data as an array. + \param imageSequence the actually captured image sequence number + */ + virtual void GetRgb(unsigned char* rgbArray, int& imageSequence); + /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence); + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // /*! // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes // \param bufferSize buffer size the buffer should be reset to // */ // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief Set file name where the data is recorded \param inputFileName name of input file which should be played */ virtual void SetInputFileName(std::string inputFileName); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraMITKPlayerDevice(); ~ToFCameraMITKPlayerDevice(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief Thread method continuously acquiring images from the specified input file */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief Clean up memory (pixel buffers) */ void CleanUpDataBuffers(); /*! \brief Allocate pixel buffers */ void AllocateDataBuffers(); ToFCameraMITKPlayerController::Pointer m_Controller; ///< member holding the corresponding controller std::string m_InputFileName; ///< member holding the file name of the current input file private: float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images + unsigned char** m_RGBDataBuffer; ///< buffer holding the last rgb images }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraPMDCamBoardDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDCamBoardDevice.cpp index d67babacb3..5bbe284f84 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDCamBoardDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDCamBoardDevice.cpp @@ -1,79 +1,79 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDCamBoardDevice.h" #include "mitkToFCameraPMDCamBoardController.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" namespace mitk { ToFCameraPMDCamBoardDevice::ToFCameraPMDCamBoardDevice() { m_Controller = ToFCameraPMDCamBoardController::New(); } ToFCameraPMDCamBoardDevice::~ToFCameraPMDCamBoardDevice() { } void ToFCameraPMDCamBoardDevice::SetRegionOfInterest(unsigned int leftUpperCornerX, unsigned int leftUpperCornerY, unsigned int width, unsigned int height) { if (m_Controller.IsNotNull()) { dynamic_cast(m_Controller.GetPointer())->SetRegionOfInterest(leftUpperCornerX,leftUpperCornerY,width,height); } } void ToFCameraPMDCamBoardDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraPMDCamBoardController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); bool boolValue = false; - GetBoolProperty(propertyValue, boolValue); + GetBoolProperty(propertyKey, boolValue); if (strcmp(propertyKey, "SetFPNCalibration") == 0) { myController->SetFPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetFPPNCalibration") == 0) { myController->SetFPPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetLinearityCalibration") == 0) { myController->SetLinearityCalibration(boolValue); } else if (strcmp(propertyKey, "SetLensCalibration") == 0) { myController->SetLensCalibration(boolValue); } else if (strcmp(propertyKey, "SetExposureMode") == 0) { if (boolValue) { myController->SetExposureMode(1); } else { myController->SetExposureMode(0); } } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDCamCubeDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDCamCubeDevice.cpp index 7d5e2949a8..fda0b81dcc 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDCamCubeDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDCamCubeDevice.cpp @@ -1,71 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDCamCubeDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" namespace mitk { ToFCameraPMDCamCubeDevice::ToFCameraPMDCamCubeDevice() { m_Controller = ToFCameraPMDCamCubeController::New(); } ToFCameraPMDCamCubeDevice::~ToFCameraPMDCamCubeDevice() { } void ToFCameraPMDCamCubeDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraPMDDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraPMDCamCubeController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); bool boolValue = false; - GetBoolProperty(propertyValue, boolValue); + GetBoolProperty(propertyKey, boolValue); if (strcmp(propertyKey, "SetFPNCalibration") == 0) { myController->SetFPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetFPPNCalibration") == 0) { myController->SetFPPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetLinearityCalibration") == 0) { myController->SetLinearityCalibration(boolValue); } else if (strcmp(propertyKey, "SetLensCalibration") == 0) { myController->SetLensCalibration(boolValue); } else if (strcmp(propertyKey, "SetExposureMode") == 0) { if (boolValue) { myController->SetExposureMode(1); } else { myController->SetExposureMode(0); } } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp index afbec13d99..e369ab3c70 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp @@ -1,409 +1,410 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraPMDDevice::ToFCameraPMDDevice() : m_SourceDataBuffer(NULL), m_SourceDataArray(NULL) { } ToFCameraPMDDevice::~ToFCameraPMDDevice() { this->CleanUpSourceData(); + CleanupPixelArrays(); } bool ToFCameraPMDDevice::ConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_SourceDataSize = m_Controller->GetSourceDataStructSize(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffers AllocatePixelArrays(); this->AllocateSourceData(); m_CameraConnected = true; } } return ok; } bool ToFCameraPMDDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } } return ok; } void ToFCameraPMDDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); //this->m_Controller->GetSourceData(this->m_SourceDataArray); this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraPMDDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool ToFCameraPMDDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraPMDDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraPMDDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraPMDDevice* toFCameraDevice = (ToFCameraPMDDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the source data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { // buffer overflow //MITK_INFO << "Buffer overflow!! "; //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { //itksys::SystemTools::Delay(10); overflow = false; } /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! END TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // void ToFCameraPMDDevice::ResetBuffer(int bufferSize) // { // this->m_BufferSize = bufferSize; // this->m_CurrentPos = -1; // this->m_FreePos = 0; // } void ToFCameraPMDDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDDevice::GetIntensities(float* intensityArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraPMDDevice::GetDistances(float* distanceArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence) + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray); this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray); this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray); memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); m_ImageMutex->Unlock(); int u, v; for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { u = i*this->m_CaptureWidth+j; v = (i+1)*this->m_CaptureWidth-1-j; distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in minimeter //distanceArray[u] = this->m_DistanceArray[v]; // unit in meter amplitudeArray[u] = this->m_AmplitudeArray[v]; intensityArray[u] = this->m_IntensityArray[v]; } } } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } ToFCameraPMDController::Pointer ToFCameraPMDDevice::GetController() { return this->m_Controller; } void ToFCameraPMDDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; - GetIntProperty(propertyValue, modulationFrequency); + GetIntProperty(propertyKey, modulationFrequency); m_Controller->SetModulationFrequency(modulationFrequency); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; - GetIntProperty(propertyValue, integrationTime); + GetIntProperty(propertyKey, integrationTime); m_Controller->SetIntegrationTime(integrationTime); } } void ToFCameraPMDDevice::AllocateSourceData() { // clean up if array and data have already been allocated CleanUpSourceData(); // (re-) allocate memory this->m_SourceDataArray = new char[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;} this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize]; } } void ToFCameraPMDDevice::CleanUpSourceData() { if (m_SourceDataArray) { delete[] m_SourceDataArray; } if (m_SourceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_SourceDataBuffer[i]; } delete[] this->m_SourceDataBuffer; } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDDevice.h b/Modules/ToFHardware/mitkToFCameraPMDDevice.h index 963d4baf90..cbaea80758 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDDevice.h +++ b/Modules/ToFHardware/mitkToFCameraPMDDevice.h @@ -1,153 +1,153 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraPMDDevice_h #define __mitkToFCameraPMDDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraPMDController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of PMD ToF devices. * ToFCameraPMDDevice internally holds an instance of ToFCameraPMDController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraPMDDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraPMDDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence); + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // /*! // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes // \param bufferSize buffer size the buffer should be reset to // */ // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ ToFCameraPMDController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraPMDDevice(); ~ToFCameraPMDDevice(); /*! \brief method for allocating m_SourceDataArray and m_SourceDataBuffer */ virtual void AllocateSourceData(); /*! \brief method for cleaning up memory allocated for m_SourceDataArray and m_SourceDataBuffer */ virtual void CleanUpSourceData(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); ToFCameraPMDController::Pointer m_Controller; ///< corresponding CameraController char** m_SourceDataBuffer; ///< buffer holding the last acquired images char* m_SourceDataArray; ///< array holding the current PMD source data private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraPMDPlayerDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDPlayerDevice.cpp index 8bd049a3cc..7aecfe9c6d 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDPlayerDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDPlayerDevice.cpp @@ -1,47 +1,47 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDPlayerDevice.h" #include "mitkToFCameraPMDPlayerController.h" #include "itkMultiThreader.h" namespace mitk { ToFCameraPMDPlayerDevice::ToFCameraPMDPlayerDevice() { m_Controller = ToFCameraPMDPlayerController::New(); m_InputFileName = ""; } ToFCameraPMDPlayerDevice::~ToFCameraPMDPlayerDevice() { } void ToFCameraPMDPlayerDevice::SetProperty(const char* propertyKey, BaseProperty* propertyValue) { this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraPMDPlayerController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); std::string strValue; - GetStringProperty(propertyValue, strValue); + GetStringProperty(propertyKey, strValue); if (strcmp(propertyKey, "PMDFileName") == 0) { myController->SetPMDFileName(strValue); } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDRawDataCamBoardDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDRawDataCamBoardDevice.cpp index c152f68d72..b6ebfe6d69 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDRawDataCamBoardDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDRawDataCamBoardDevice.cpp @@ -1,102 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDRawDataCamBoardDevice.h" #include "mitkToFCameraPMDCamBoardController.h" // vtk includes #include "vtkSmartPointer.h" namespace mitk { ToFCameraPMDRawDataCamBoardDevice::ToFCameraPMDRawDataCamBoardDevice() { m_Controller = ToFCameraPMDCamBoardController::New(); } ToFCameraPMDRawDataCamBoardDevice::~ToFCameraPMDRawDataCamBoardDevice() { } void ToFCameraPMDRawDataCamBoardDevice::GetChannelSourceData(short* sourceData, vtkShortArray* vtkChannelArray ) { int i = 0; //unsigned int channelDataPosition = 0; unsigned int channelSize = (this->GetCaptureHeight()*this->GetCaptureWidth()*2); this->SetChannelSize(channelSize); signed short* channel1; signed short* channel2; signed short* channel3; signed short* channel4; vtkSmartPointer cvtkChannelArray = vtkShortArray::New(); cvtkChannelArray->SetNumberOfComponents(channelSize); cvtkChannelArray->SetNumberOfTuples(4); cvtkChannelArray->Allocate(1); channel1 = sourceData; cvtkChannelArray->InsertTupleValue(0,channel1); sourceData += channelSize; channel2 = sourceData; cvtkChannelArray->InsertTupleValue(1,channel2); sourceData += channelSize; channel3 = sourceData; cvtkChannelArray->InsertTupleValue(2,channel3); sourceData += channelSize; channel4 = sourceData; cvtkChannelArray->InsertTupleValue(3,channel4); vtkChannelArray->DeepCopy(cvtkChannelArray); cvtkChannelArray->Delete(); } void ToFCameraPMDRawDataCamBoardDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraPMDRawDataDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraPMDCamBoardController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); bool boolValue = false; - GetBoolProperty(propertyValue, boolValue); + GetBoolProperty(propertyKey, boolValue); if (strcmp(propertyKey, "SetFPNCalibration") == 0) { myController->SetFPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetFPPNCalibration") == 0) { myController->SetFPPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetLinearityCalibration") == 0) { myController->SetLinearityCalibration(boolValue); } else if (strcmp(propertyKey, "SetLensCalibration") == 0) { myController->SetLensCalibration(boolValue); } else if (strcmp(propertyKey, "SetExposureMode") == 0) { if (boolValue) { myController->SetExposureMode(1); } else { myController->SetExposureMode(0); } } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDRawDataCamCubeDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDRawDataCamCubeDevice.cpp index 972a9e90dd..ac3cc2ceef 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDRawDataCamCubeDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDRawDataCamCubeDevice.cpp @@ -1,105 +1,105 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDRawDataCamCubeDevice.h" #include "mitkToFCameraPMDCamCubeController.h" // vtk includes #include "vtkSmartPointer.h" namespace mitk { ToFCameraPMDRawDataCamCubeDevice::ToFCameraPMDRawDataCamCubeDevice() { m_Controller = ToFCameraPMDCamCubeController::New(); } ToFCameraPMDRawDataCamCubeDevice::~ToFCameraPMDRawDataCamCubeDevice() { } void ToFCameraPMDRawDataCamCubeDevice::GetChannelSourceData(short* sourceData, vtkShortArray* vtkChannelArray ) { int i = 0; unsigned int channelSize = (this->GetCaptureHeight()*this->GetCaptureWidth()*2); this->SetChannelSize(channelSize); signed short* channel1; signed short* channel2; signed short* channel3; signed short* channel4; vtkSmartPointer tempVTKChannelArray = vtkShortArray::New(); tempVTKChannelArray->SetNumberOfComponents(channelSize); tempVTKChannelArray->SetNumberOfTuples(4); tempVTKChannelArray->Allocate(1); sourceData += 256; channel1 = sourceData; tempVTKChannelArray->InsertTupleValue(0,channel1); sourceData += channelSize; sourceData += 256; channel2 = sourceData; tempVTKChannelArray->InsertTupleValue(1,channel2); sourceData += channelSize; sourceData += 256; channel3 = sourceData; tempVTKChannelArray->InsertTupleValue(2,channel3); sourceData += channelSize; sourceData += 256; channel4 = sourceData; tempVTKChannelArray->InsertTupleValue(3,channel4); vtkChannelArray->DeepCopy(tempVTKChannelArray); tempVTKChannelArray->Delete(); } void ToFCameraPMDRawDataCamCubeDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraPMDRawDataDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraPMDCamCubeController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); bool boolValue = false; - GetBoolProperty(propertyValue, boolValue); + GetBoolProperty(propertyKey, boolValue); if (strcmp(propertyKey, "SetFPNCalibration") == 0) { myController->SetFPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetFPPNCalibration") == 0) { myController->SetFPPNCalibration(boolValue); } else if (strcmp(propertyKey, "SetLinearityCalibration") == 0) { myController->SetLinearityCalibration(boolValue); } else if (strcmp(propertyKey, "SetLensCalibration") == 0) { myController->SetLensCalibration(boolValue); } else if (strcmp(propertyKey, "SetExposureMode") == 0) { if (boolValue) { myController->SetExposureMode(1); } else { myController->SetExposureMode(0); } } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp index 3133a60f56..3ac6750a4c 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp @@ -1,465 +1,465 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDRawDataDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraPMDRawDataDevice::ToFCameraPMDRawDataDevice() : m_SourceDataBuffer(NULL), m_SourceDataArray(NULL), m_ShortSourceData(NULL) { m_RawDataSource = ThreadedToFRawDataReconstruction::New(); } ToFCameraPMDRawDataDevice::~ToFCameraPMDRawDataDevice() { this->CleanUpSourceData(); } bool ToFCameraPMDRawDataDevice::ConnectCamera() { bool ok = false; if (m_Controller.IsNotNull()) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_SourceDataSize = m_Controller->GetSourceDataStructSize(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffers this->AllocatePixelArrays(); this->AllocateSourceData(); m_CameraConnected = true; } } return ok; } bool ToFCameraPMDRawDataDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } } return ok; } void ToFCameraPMDRawDataDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(100); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraPMDRawDataDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool ToFCameraPMDRawDataDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraPMDRawDataDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraPMDRawDataDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraPMDRawDataDevice* toFCameraDevice = (ToFCameraPMDRawDataDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the source data from the camera and write it at the next free position in the buffer // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); vtkShortArray* channelData = vtkShortArray::New(); //toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetShortSourceData(toFCameraDevice->m_ShortSourceData); toFCameraDevice->GetChannelSourceData( toFCameraDevice->m_ShortSourceData, channelData ); //toFCameraDevice->m_ImageMutex->Unlock(); if(!toFCameraDevice->m_RawDataSource->GetInit()) { toFCameraDevice->m_RawDataSource->Initialize(toFCameraDevice->m_CaptureWidth, toFCameraDevice->m_CaptureHeight, toFCameraDevice->m_Controller->GetModulationFrequency(), toFCameraDevice->GetChannelSize()); } toFCameraDevice->m_RawDataSource->SetChannelData(channelData); toFCameraDevice->m_RawDataSource->Update(); toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataArray); toFCameraDevice->m_RawDataSource->GetAllData(toFCameraDevice->m_DistanceArray, toFCameraDevice->m_AmplitudeArray, toFCameraDevice->m_IntensityArray); toFCameraDevice->m_ImageMutex->Unlock(); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } channelData->Delete(); if (overflow) { overflow = false; } /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! END TODO Buffer Handling currently only works for buffer size 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // void ToFCameraPMDDevice::ResetBuffer(int bufferSize) // { // this->m_BufferSize = bufferSize; // this->m_CurrentPos = -1; // this->m_FreePos = 0; // } void ToFCameraPMDRawDataDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { if (m_CameraActive) { memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetIntensities(float* intensityArray, int& imageSequence) { if (m_CameraActive) { memcpy(intensityArray, this->m_IntensityArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetDistances(float* distanceArray, int& imageSequence) { if (m_CameraActive) { memcpy(distanceArray, this->m_DistanceArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence) + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } memcpy(distanceArray, this->m_DistanceArray, this->m_PixelNumber*sizeof(float)); memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_PixelNumber*sizeof(float)); memcpy(intensityArray, this->m_IntensityArray, this->m_PixelNumber*sizeof(float)); memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::XYAxisFlipImage( float* imageData, float* &flippedData, int xAxis, int yAxis, int dimension ) { int captureWidth = this->GetCaptureWidth(); int captureHeight = this->GetCaptureHeight(); // //flips image around x- axis (horizontal axis) // if(xAxis == 1 && yAxis != 1) { for (int i=0; im_Controller; } void ToFCameraPMDRawDataDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; - GetIntProperty(propertyValue, modulationFrequency); + GetIntProperty(propertyKey, modulationFrequency); m_Controller->SetModulationFrequency(modulationFrequency); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; - GetIntProperty(propertyValue, integrationTime); + GetIntProperty(propertyKey, integrationTime); m_Controller->SetIntegrationTime(integrationTime); } } void ToFCameraPMDRawDataDevice::CleanupPixelArrays() { if (m_IntensityArray) { delete [] m_IntensityArray; } if (m_DistanceArray) { delete [] m_DistanceArray; } if (m_AmplitudeArray) { delete [] m_AmplitudeArray; } if (m_ShortSourceData) { delete [] m_ShortSourceData; } } void ToFCameraPMDRawDataDevice::AllocatePixelArrays() { // free memory if it was already allocated CleanupPixelArrays(); // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_ShortSourceData = new short[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_ShortSourceData[i]=0.0;} } void ToFCameraPMDRawDataDevice::AllocateSourceData() { // clean up if array and data have already been allocated CleanUpSourceData(); // (re-) allocate memory this->m_SourceDataArray = new char[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;} this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize]; } } void ToFCameraPMDRawDataDevice::CleanUpSourceData() { if (m_SourceDataArray) { delete[] m_SourceDataArray; } if (m_SourceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_SourceDataBuffer[i]; } delete[] this->m_SourceDataBuffer; } } } diff --git a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.h b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.h index a63ef493f4..b687e75a34 100644 --- a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.h +++ b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.h @@ -1,175 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraPMDRawDataDevice_h #define __mitkToFCameraPMDRawDataDevice_h #include "mitkToFHardwareExports.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraPMDController.h" #include "mitkThreadedToFRawDataReconstruction.h" namespace mitk { /** * @brief Interface for all representations of PMD ToF devices. * ToFCameraPMDDevice internally holds an instance of ToFCameraPMDController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraPMDRawDataDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraPMDRawDataDevice , ToFCameraDevice ); itkNewMacro( Self ); itkSetMacro(ChannelSize, int); itkGetMacro(ChannelSize, int); /*! \brief opens a connection to the ToF camera */ virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, - int requiredImageSequence, int& capturedImageSequence); + int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated // /*! // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes // \param bufferSize buffer size the buffer should be reset to // */ // virtual void ResetBuffer(int bufferSize) = 0; //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ ToFCameraPMDController::Pointer GetController(); virtual void GetChannelSourceData(short* /*sourceData*/, vtkShortArray* /*vtkChannelArray*/ ){}; /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraPMDRawDataDevice(); ~ToFCameraPMDRawDataDevice(); /*! \brief method for allocating m_SourceDataArray and m_SourceDataBuffer */ virtual void AllocateSourceData(); /*! \brief method for cleaning up memory allocated for m_SourceDataArray and m_SourceDataBuffer */ virtual void CleanUpSourceData(); /*! \brief method for allocating memory for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void AllocatePixelArrays(); /*! \brief method for cleanup memory allocated for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void CleanupPixelArrays(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); /*! \brief gets the image data and flips it according to user needs Caution! The user is responsible for allocating and deleting the data. \param imageData contains array to the input data. \param flippedData contains flipped output array - Caution! The user is responsible for allocating and deleting the data. Size should be equal to imageData! \param xAxis flag is set to flip around x axis (1 - set, 0 - not set). \param yAxis flag is set to flip around y axis (1 - set, 0 - not set). \param dimension contains the extend of the z dimension (preset is 1) */ void XYAxisFlipImage( float* imageData, float* &flippedData, int xAxis, int yAxis, int dimension = 1 ); ToFCameraPMDController::Pointer m_Controller; ///< corresponding CameraController ThreadedToFRawDataReconstruction::Pointer m_RawDataSource; char** m_SourceDataBuffer; ///< buffer holding the last acquired images char* m_SourceDataArray; ///< array holding the current PMD source data short* m_ShortSourceData; ///< array holding the current PMD raw data private: //member variables int m_ChannelSize; ///< member holds the size of a single raw data channel }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFConfig.h.in b/Modules/ToFHardware/mitkToFConfig.h.in index abd6154cd6..3c89f9486a 100644 --- a/Modules/ToFHardware/mitkToFConfig.h.in +++ b/Modules/ToFHardware/mitkToFConfig.h.in @@ -1,15 +1,16 @@ /* mitToFConfig.h this file is generated. Do not change! */ #define MITK_TOF_PMDCAMBOARD_SOURCE_PLUGIN "@MITK_TOF_PMD_CAMBOARD_SOURCE@" #define MITK_TOF_PMDCAMBOARD_PROCESSING_PLUGIN "@MITK_TOF_PMD_CAMBOARD_PROC@" #define MITK_TOF_PMDO3_SOURCE_PLUGIN "@MITK_TOF_PMD_O3D_SOURCE@" #define MITK_TOF_PMDO3_PROCESSING_PLUGIN "@MITK_TOF_PMD_O3D_PROC@" #define MITK_TOF_PMDFILE_SOURCE_PLUGIN "@MITK_TOF_PMD_FILE_SOURCE@" #define MITK_TOF_PMDCAMCUBE_SOURCE_PLUGIN "@MITK_TOF_PMD_CAMCUBE_SOURCE@" #define MITK_TOF_PMDCAMCUBE_PROCESSING_PLUGIN "@MITK_TOF_PMD_CAMCUBE_PROC@" #define MITK_TOF_PLATFORM "@_PLATFORM_STRING@" #define MITK_TOF_DATA_DIR "@MITK_DATA_DIR@/ToF-Data" #define MITK_TOF_CAMERAS "@MITK_TOF_AVAILABLE_CAMERAS@" +#cmakedefine MITK_USE_TOF_KINECT diff --git a/Modules/ToFHardware/mitkToFHardware.cmake b/Modules/ToFHardware/mitkToFHardware.cmake index 8e2fd01aff..f8e3054a40 100644 --- a/Modules/ToFHardware/mitkToFHardware.cmake +++ b/Modules/ToFHardware/mitkToFHardware.cmake @@ -1,116 +1,129 @@ #option MITK_USE_TOF_HARDWARE -if(WIN32) - if(CMAKE_CL_64) - set(_PLATFORM_STRING "W64") - else(CMAKE_CL_64) - set(_PLATFORM_STRING "W32") - endif(CMAKE_CL_64) -else(WIN32) - if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(_PLATFORM_STRING "L64") - else(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(_PLATFORM_STRING "L32") - endif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") -endif(WIN32) +IF(WIN32) + IF(CMAKE_CL_64) + SET(_PLATFORM_STRING "W64") + ELSE(CMAKE_CL_64) + SET(_PLATFORM_STRING "W32") + ENDIF(CMAKE_CL_64) +ELSE(WIN32) + IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + SET(_PLATFORM_STRING "L64") + ELSE(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + SET(_PLATFORM_STRING "L32") + ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") +ENDIF(WIN32) -set(MITK_TOF_AVAILABLE_CAMERAS MITK Player) +SET(MITK_TOF_AVAILABLE_CAMERAS MITK Player) + +OPTION(MITK_ENABLE_TOF_HARDWARE "Support for range cameras" OFF) +IF(MITK_ENABLE_TOF_HARDWARE) -option(MITK_ENABLE_TOF_HARDWARE "Support for range cameras" OFF) -if(MITK_ENABLE_TOF_HARDWARE) - #Begin PMD Camcube hardware -option(MITK_USE_TOF_PMDCAMCUBE "Enable support for PMD camcube" OFF) +OPTION(MITK_USE_TOF_PMDCAMCUBE "Enable support for PMD camcube" OFF) # only if PMD Camcube is enabled -if(MITK_USE_TOF_PMDCAMCUBE) - find_library(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") - get_filename_component(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) - set(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) - find_path(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") - set(MITK_TOF_PMD_CAMCUBE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/camcube3.${_PLATFORM_STRING}.pap) - set(MITK_TOF_PMD_CAMCUBE_PROC ${MITK_PMD_SDK_DIR}/plugins/camcubeproc.${_PLATFORM_STRING}.ppp) - set(MITK_TOF_PMD_FILE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp) - set(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamCube 2.0/3.0,PMD CamCubeRaw 2.0/3.0,PMD Player,PMD Raw Data Player) -# file(GLOB MITK_TOF_PMD_CAMCUBE_SOURCE camcube3.${_PLATFORM_STRING}.pap) -# file(GLOB MITK_TOF_PMD_CAMCUBE_PROC camcubeproc.${_PLATFORM_STRING}.ppp) -# file(GLOB MITK_TOF_PMD_FILE_SOURCE pmdfile.${_PLATFORM_STRING}.pcp) - if(WIN32) +IF(MITK_USE_TOF_PMDCAMCUBE) + FIND_LIBRARY(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") + GET_FILENAME_COMPONENT(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) + SET(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) + FIND_PATH(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") + SET(MITK_TOF_PMD_CAMCUBE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/camcube3.${_PLATFORM_STRING}.pap) + SET(MITK_TOF_PMD_CAMCUBE_PROC ${MITK_PMD_SDK_DIR}/plugins/camcubeproc.${_PLATFORM_STRING}.ppp) + SET(MITK_TOF_PMD_FILE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp) + SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamCube 2.0/3.0,PMD CamCubeRaw 2.0/3.0,PMD Player,PMD Raw Data Player) +# FILE(GLOB MITK_TOF_PMD_CAMCUBE_SOURCE camcube3.${_PLATFORM_STRING}.pap) +# FILE(GLOB MITK_TOF_PMD_CAMCUBE_PROC camcubeproc.${_PLATFORM_STRING}.ppp) +# FILE(GLOB MITK_TOF_PMD_FILE_SOURCE pmdfile.${_PLATFORM_STRING}.pcp) + IF(WIN32) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/bin/pmdaccess2.dll CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camcube3.W32.pap CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camcubeproc.W32.ppp CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camcube3.W64.pap CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camcubeproc.W64.ppp CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/pmdfile.W32.pcp CONFIGURATIONS Release) - endif(WIN32) -endif(MITK_USE_TOF_PMDCAMCUBE) + ENDIf(WIN32) +ENDIF(MITK_USE_TOF_PMDCAMCUBE) #End PMD Camcube Hardware #Begin PMD CamBoard hardware -option(MITK_USE_TOF_PMDCAMBOARD "Enable support for PMD camboard" OFF) +OPTION(MITK_USE_TOF_PMDCAMBOARD "Enable support for PMD camboard" OFF) # only if PMD CamBoard is enabled -if(MITK_USE_TOF_PMDCAMBOARD) - find_library(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") - get_filename_component(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) - set(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) - find_path(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") - set(MITK_TOF_PMD_CAMBOARD_SOURCE ${MITK_PMD_SDK_DIR}/plugins/camboard.${_PLATFORM_STRING}.pap) - set(MITK_TOF_PMD_CAMBOARD_PROC ${MITK_PMD_SDK_DIR}/plugins/camboardproc.${_PLATFORM_STRING}.ppp) - set(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamBoard,PMD CamBoardRaw) -# file(GLOB MITK_TOF_PMD_CAMBOARD_SOURCE camboard.${_PLATFORM_STRING}.pap) -# file(GLOB MITK_TOF_PMD_CAMBOARD_PROC camboardproc.${_PLATFORM_STRING}.ppp) -# file(GLOB MITK_TOF_PMD_FILE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp) - if(WIN32) - install(FILES ${MITK_PMD_SDK_DIR}/bin/pmdaccess2.dll DESTINATION bin CONFIGURATIONS Release) - install(FILES ${MITK_PMD_SDK_DIR}/plugins/camboard.W32.pap DESTINATION bin CONFIGURATIONS Release) - install(FILES ${MITK_PMD_SDK_DIR}/plugins/camboardproc.W32.ppp DESTINATION bin CONFIGURATIONS Release) -# install(FILES ${MITK_PMD_SDK_DIR}/plugins/camboard.W64.pap DESTINATION bin CONFIGURATIONS Release) -# install(FILES ${MITK_PMD_SDK_DIR}/plugins/camboardproc.W64.ppp DESTINATION bin CONFIGURATIONS Release) -# install(FILES ${MITK_PMD_SDK_DIR}/plugins/pmdfile.W32.pcp DESTINATION bin CONFIGURATIONS Release) - endif(WIN32) -endif(MITK_USE_TOF_PMDCAMBOARD) +IF(MITK_USE_TOF_PMDCAMBOARD) + FIND_LIBRARY(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") + GET_FILENAME_COMPONENT(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) + SET(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) + FIND_PATH(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") + SET(MITK_TOF_PMD_CAMBOARD_SOURCE ${MITK_PMD_SDK_DIR}/plugins/camboard.${_PLATFORM_STRING}.pap) + SET(MITK_TOF_PMD_CAMBOARD_PROC ${MITK_PMD_SDK_DIR}/plugins/camboardproc.${_PLATFORM_STRING}.ppp) + SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamBoard,PMD CamBoardRaw) +# FILE(GLOB MITK_TOF_PMD_CAMBOARD_SOURCE camboard.${_PLATFORM_STRING}.pap) +# FILE(GLOB MITK_TOF_PMD_CAMBOARD_PROC camboardproc.${_PLATFORM_STRING}.ppp) +# FILE(GLOB MITK_TOF_PMD_FILE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp) + IF(WIN32) + INSTALL(FILES ${MITK_PMD_SDK_DIR}/bin/pmdaccess2.dll DESTINATION bin CONFIGURATIONS Release) + INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camboard.W32.pap DESTINATION bin CONFIGURATIONS Release) + INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camboardproc.W32.ppp DESTINATION bin CONFIGURATIONS Release) +# INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camboard.W64.pap DESTINATION bin CONFIGURATIONS Release) +# INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/camboardproc.W64.ppp DESTINATION bin CONFIGURATIONS Release) +# INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/pmdfile.W32.pcp DESTINATION bin CONFIGURATIONS Release) + ENDIf(WIN32) +ENDIF(MITK_USE_TOF_PMDCAMBOARD) #End PMD CamBoard Hardware #Begin MESA SR4000 hardware -option(MITK_USE_TOF_MESASR4000 "Enable support for MESA SR4000" OFF) +OPTION(MITK_USE_TOF_MESASR4000 "Enable support for MESA SR4000" OFF) # only if MESA SR4000 is enabled -if(MITK_USE_TOF_MESASR4000) - find_library(MITK_MESA_LIB libMesaSR DOC "MESA access library.") - get_filename_component(MITK_MESA_SDK_DIR ${MITK_MESA_LIB} PATH) - set(MITK_MESA_SDK_DIR ${MITK_MESA_SDK_DIR}/..) - find_path(MITK_MESA_INCLUDE_DIR libMesaSR.h ${MITK_MESA_SDK_DIR}/include DOC "Include directory of MESA-SDK.") - set(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},MESA Swissranger 4000) - if(WIN32) - install(FILES ${MITK_MESA_SDK_DIR}/bin/libMesaSR.dll DESTINATION bin CONFIGURATIONS Release) - endif(WIN32) -endif(MITK_USE_TOF_MESASR4000) +IF(MITK_USE_TOF_MESASR4000) + FIND_LIBRARY(MITK_MESA_LIB libMesaSR DOC "MESA access library.") + GET_FILENAME_COMPONENT(MITK_MESA_SDK_DIR ${MITK_MESA_LIB} PATH) + SET(MITK_MESA_SDK_DIR ${MITK_MESA_SDK_DIR}/..) + FIND_PATH(MITK_MESA_INCLUDE_DIR libMesaSR.h ${MITK_MESA_SDK_DIR}/include DOC "Include directory of MESA-SDK.") + SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},MESA Swissranger 4000) + IF(WIN32) + INSTALL(FILES ${MITK_MESA_SDK_DIR}/bin/libMesaSR.dll DESTINATION bin CONFIGURATIONS Release) + ENDIf(WIN32) +ENDIF(MITK_USE_TOF_MESASR4000) #End MESA SR4000 Hardware -if(WIN32) +IF (WIN32) #Begin PMD O3 hardware -option(MITK_USE_TOF_PMDO3 "Enable support for PMD O3 camera" OFF) +OPTION(MITK_USE_TOF_PMDO3 "Enable support for PMD O3 camera" OFF) # only if PMD O3 is enabled -if(MITK_USE_TOF_PMDO3) - find_library(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") - get_filename_component(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) - set(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) - find_path(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") - set(MITK_TOF_PMD_O3D_SOURCE ${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp) - set(MITK_TOF_PMD_O3D_PROC ${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp) - set(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD O3D) +IF(MITK_USE_TOF_PMDO3) + FIND_LIBRARY(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") + GET_FILENAME_COMPONENT(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) + SET(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/..) + FIND_PATH(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") + SET(MITK_TOF_PMD_O3D_SOURCE ${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp) + SET(MITK_TOF_PMD_O3D_PROC ${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp) + SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD O3D) -# file(GLOB MITK_TOF_PMD_O3D_SOURCE o3d.${_PLATFORM_STRING}.pcp) -# file(GLOB MITK_TOF_PMD_O3D_PROC o3d.${_PLATFORM_STRING}.pcp) +# FILE(GLOB MITK_TOF_PMD_O3D_SOURCE o3d.${_PLATFORM_STRING}.pcp) +# FILE(GLOB MITK_TOF_PMD_O3D_PROC o3d.${_PLATFORM_STRING}.pcp) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/bin/pmdaccess2.dll CONFIGURATIONS Release) MITK_INSTALL(FILES ${MITK_PMD_SDK_DIR}/plugins/o3d.W32.pcp CONFIGURATIONS Release) -endif(MITK_USE_TOF_PMDO3) +ENDIF(MITK_USE_TOF_PMDO3) #End PMD O3 Hardware -endif(WIN32) +ENDIF(WIN32) -endif(MITK_ENABLE_TOF_HARDWARE) +#Begin Kinect hardware +OPTION(MITK_USE_TOF_KINECT "Enable support for Kinect camera" OFF) +# only if Kinect is enabled +IF(MITK_USE_TOF_KINECT) + FIND_LIBRARY(MITK_KINECT_LIB libOpenNI DOC "Kinect access library.") + FIND_PATH(MITK_KINECT_INCLUDE_DIR XnCppWrapper.h DOC "Include directory of Kinect camera.") + SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},Microsoft Kinect) +#TODO Installer specific stuff +# IF(WIN32) +# INSTALL(FILES ${MITK_MESA_SDK_DIR}/bin/libMesaSR.dll DESTINATION bin CONFIGURATIONS Release) +# ENDIf(WIN32) +ENDIF(MITK_USE_TOF_KINECT) +#End Kinect Hardware -configure_file(mitkToFConfig.h.in ${PROJECT_BINARY_DIR}/mitkToFConfig.h @ONLY) +ENDIF(MITK_ENABLE_TOF_HARDWARE) +CONFIGURE_FILE(mitkToFConfig.h.in ${PROJECT_BINARY_DIR}/mitkToFConfig.h @ONLY) diff --git a/Modules/ToFHardware/mitkToFImageCsvWriter.cpp b/Modules/ToFHardware/mitkToFImageCsvWriter.cpp index 6745eeb102..b39691833c 100644 --- a/Modules/ToFHardware/mitkToFImageCsvWriter.cpp +++ b/Modules/ToFHardware/mitkToFImageCsvWriter.cpp @@ -1,124 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include namespace mitk { ToFImageCsvWriter::ToFImageCsvWriter(): ToFImageWriter(), m_DistanceOutfile(NULL), m_AmplitudeOutfile(NULL), m_IntensityOutfile(NULL) { this->m_Extension = std::string(".csv"); } ToFImageCsvWriter::~ToFImageCsvWriter() { } void ToFImageCsvWriter::Open() { this->CheckForFileExtension(this->m_DistanceImageFileName); this->CheckForFileExtension(this->m_AmplitudeImageFileName); this->CheckForFileExtension(this->m_IntensityImageFileName); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_ImageSizeInBytes = this->m_PixelNumber * sizeof(float); if (this->m_DistanceImageSelected) { this->OpenCsvFile(&(this->m_DistanceOutfile), this->m_DistanceImageFileName); } if (this->m_AmplitudeImageSelected) { this->OpenCsvFile(&(this->m_AmplitudeOutfile), this->m_AmplitudeImageFileName); } if (this->m_IntensityImageSelected) { this->OpenCsvFile(&(this->m_IntensityOutfile), this->m_IntensityImageFileName); } this->m_NumOfFrames = 0; } void ToFImageCsvWriter::Close() { if (this->m_DistanceImageSelected) { this->CloseCsvFile(this->m_DistanceOutfile); } if (this->m_AmplitudeImageSelected) { this->CloseCsvFile(this->m_AmplitudeOutfile); } if (this->m_IntensityImageSelected) { this->CloseCsvFile(this->m_IntensityOutfile); } } - void ToFImageCsvWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData) + void ToFImageCsvWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData) { if (this->m_DistanceImageSelected) { this->WriteCsvFile(this->m_DistanceOutfile, distanceFloatData); } if (this->m_AmplitudeImageSelected) { this->WriteCsvFile(this->m_AmplitudeOutfile, amplitudeFloatData); } if (this->m_IntensityImageSelected) { this->WriteCsvFile(this->m_IntensityOutfile, intensityFloatData); } this->m_NumOfFrames++; } void ToFImageCsvWriter::WriteCsvFile(FILE* outfile, float* floatData) { for(int i=0; im_PixelNumber; i++) { if (this->m_NumOfFrames==0 && i==0) { fprintf(outfile, "%f", floatData[i]); } else { fprintf(outfile, ",%f", floatData[i]); } } } void ToFImageCsvWriter::OpenCsvFile(FILE** outfile, std::string outfileName) { (*outfile) = fopen( outfileName.c_str(), "w+" ); if( !outfile ) { MITK_ERROR << "Error opening outfile: " << outfileName; throw std::logic_error("Error opening outfile."); return; } } void ToFImageCsvWriter::CloseCsvFile(FILE* outfile) { if (this->m_NumOfFrames == 0) { fclose(outfile); throw std::logic_error("File is empty."); return; } fclose(outfile); } } diff --git a/Modules/ToFHardware/mitkToFImageCsvWriter.h b/Modules/ToFHardware/mitkToFImageCsvWriter.h index 37fadbe302..458f5a5b39 100644 --- a/Modules/ToFHardware/mitkToFImageCsvWriter.h +++ b/Modules/ToFHardware/mitkToFImageCsvWriter.h @@ -1,88 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFImageCsvWriter_h #define __mitkToFImageCsvWriter_h #include "mitkToFImageWriter.h" #include "mitkToFHardwareExports.h" namespace mitk { /** * @brief CSV writer class for ToF image data * * This writer class allows streaming of ToF data into a CSV file. * Writer can simultaneously save "distance", "intensity" and "amplitude" image data. * Output files are written as 1D CSV data stream. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFImageCsvWriter : public ToFImageWriter { public: /*! \brief standard ctor */ ToFImageCsvWriter(); /*! \brief standard ~ctor */ ~ToFImageCsvWriter(); mitkClassMacro( ToFImageCsvWriter , ToFImageWriter ); itkNewMacro( Self ); /*! \brief Checks for file extensions and opens the output files */ void Open(); /*! \brief Closes the output files */ void Close(); /*! \brief Pushes the image data to the output files \param data from distance, amplitude and intensity images as float values */ - void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData); + void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData=0); protected: Image::Pointer m_MitkImage; ///< mitk image used for pic header creation FILE* m_DistanceOutfile; ///< file for distance image FILE* m_AmplitudeOutfile; ///< file for amplitude image FILE* m_IntensityOutfile; ///< file for intensity image - private: /*! \brief opens CSV output file \param output file, name of the output file */ void OpenCsvFile(FILE** outfile, std::string outfileName); /*! \brief closes CSV output file \param output file */ void CloseCsvFile(FILE* outfile); /*! \brief writes the data to the CSV output file \param output file, data array of float values */ void WriteCsvFile(FILE* outfile, float* floatData); }; } //END mitk namespace #endif // __mitkToFImageCsvWriter_h diff --git a/Modules/ToFHardware/mitkToFImageGrabber.cpp b/Modules/ToFHardware/mitkToFImageGrabber.cpp index 65700cbe47..992d20bc8f 100644 --- a/Modules/ToFHardware/mitkToFImageGrabber.cpp +++ b/Modules/ToFHardware/mitkToFImageGrabber.cpp @@ -1,254 +1,279 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFImageGrabber.h" #include "mitkToFCameraPMDCamCubeDevice.h" #include "itkCommand.h" namespace mitk { ToFImageGrabber::ToFImageGrabber():m_CaptureWidth(204),m_CaptureHeight(204),m_PixelNumber(41616),m_ImageSequence(0), - m_IntensityArray(NULL), m_DistanceArray(NULL), m_AmplitudeArray(NULL), m_SourceDataArray(NULL) + m_IntensityArray(NULL), m_DistanceArray(NULL), m_AmplitudeArray(NULL), m_SourceDataArray(NULL), m_RgbDataArray(NULL) { // Create the output. We use static_cast<> here because we know the default // output must be of type TOutputImage OutputImageType::Pointer output0 = static_cast(this->MakeOutput(0).GetPointer()); OutputImageType::Pointer output1 = static_cast(this->MakeOutput(1).GetPointer()); OutputImageType::Pointer output2 = static_cast(this->MakeOutput(2).GetPointer()); + OutputImageType::Pointer output3 = static_cast(this->MakeOutput(3).GetPointer()); mitk::ImageSource::SetNumberOfRequiredOutputs(3); mitk::ImageSource::SetNthOutput(0, output0.GetPointer()); mitk::ImageSource::SetNthOutput(1, output1.GetPointer()); mitk::ImageSource::SetNthOutput(2, output2.GetPointer()); + mitk::ImageSource::SetNthOutput(3, output3.GetPointer()); } ToFImageGrabber::~ToFImageGrabber() { - if (m_IntensityArray||m_AmplitudeArray||m_DistanceArray) + if (m_IntensityArray||m_AmplitudeArray||m_DistanceArray||m_RgbDataArray) { if (m_ToFCameraDevice) { m_ToFCameraDevice->RemoveObserver(m_DeviceObserverTag); } this->DisconnectCamera(); this->CleanUpImageArrays(); } } mitk::ImageSource::DataObjectPointer mitk::ImageSource::MakeOutput(unsigned int) { return static_cast(OutputImageType::New().GetPointer()); } void ToFImageGrabber::GenerateData() { int requiredImageSequence = 0; int capturedImageSequence = 0; + unsigned int dimensions[3]; + dimensions[0] = this->m_ToFCameraDevice->GetCaptureWidth(); + dimensions[1] = this->m_ToFCameraDevice->GetCaptureHeight(); + dimensions[2] = 1; + mitk::PixelType FloatType = MakeScalarPixelType(); + // acquire new image data + this->m_ToFCameraDevice->GetAllImages(this->m_DistanceArray, this->m_AmplitudeArray, this->m_IntensityArray, this->m_SourceDataArray, + requiredImageSequence, this->m_ImageSequence, this->m_RgbDataArray ); mitk::Image::Pointer distanceImage = this->GetOutput(0); - mitk::Image::Pointer amplitudeImage = this->GetOutput(1); - mitk::Image::Pointer intensityImage = this->GetOutput(2); - if (!distanceImage->IsInitialized()) { distanceImage->ReleaseData(); - amplitudeImage->ReleaseData(); - intensityImage->ReleaseData(); - - unsigned int dimensions[3]; - dimensions[0] = this->m_ToFCameraDevice->GetCaptureWidth(); - dimensions[1] = this->m_ToFCameraDevice->GetCaptureHeight(); - dimensions[2] = 1; - - mitk::PixelType FloatType = MakeScalarPixelType(); - distanceImage->Initialize(FloatType, 3, dimensions, 1); + } + mitk::Image::Pointer amplitudeImage = this->GetOutput(1); + if (!amplitudeImage->IsInitialized()) + { + amplitudeImage->ReleaseData(); amplitudeImage->Initialize(FloatType, 3, dimensions, 1); + } + mitk::Image::Pointer intensityImage = this->GetOutput(2); + if (!intensityImage->IsInitialized()) + { + intensityImage->ReleaseData(); intensityImage->Initialize(FloatType, 3, dimensions, 1); } - if (m_DistanceArray&&m_AmplitudeArray&&m_IntensityArray) + mitk::Image::Pointer rgbImage = this->GetOutput(3); + if (!rgbImage->IsInitialized()) { - this->m_ToFCameraDevice->GetAllImages(this->m_DistanceArray, this->m_AmplitudeArray, this->m_IntensityArray, this->m_SourceDataArray, - requiredImageSequence, this->m_ImageSequence ); + rgbImage->ReleaseData(); + rgbImage->Initialize(mitk::PixelType(MakePixelType, 3>()),3,dimensions,1); + } - capturedImageSequence = this->m_ImageSequence; + capturedImageSequence = this->m_ImageSequence; + if (m_DistanceArray) + { distanceImage->SetSlice(this->m_DistanceArray, 0, 0, 0); + } + if (m_AmplitudeArray) + { amplitudeImage->SetSlice(this->m_AmplitudeArray, 0, 0, 0); + } + if (m_IntensityArray) + { intensityImage->SetSlice(this->m_IntensityArray, 0, 0, 0); } + if (m_RgbDataArray) + { + rgbImage->SetSlice(this->m_RgbDataArray, 0, 0, 0); + } } bool ToFImageGrabber::ConnectCamera() { bool ok = m_ToFCameraDevice->ConnectCamera(); if (ok) { m_CaptureWidth = m_ToFCameraDevice->GetCaptureWidth(); m_CaptureHeight = m_ToFCameraDevice->GetCaptureHeight(); m_PixelNumber = m_CaptureWidth * m_CaptureHeight; m_SourceDataSize = m_ToFCameraDevice->GetSourceDataSize(); AllocateImageArrays(); } return ok; } bool ToFImageGrabber::DisconnectCamera() { bool success = m_ToFCameraDevice->DisconnectCamera(); return success; } void ToFImageGrabber::StartCamera() { m_ToFCameraDevice->StartCamera(); } void ToFImageGrabber::StopCamera() { m_ToFCameraDevice->StopCamera(); } bool ToFImageGrabber::IsCameraActive() { return m_ToFCameraDevice->IsCameraActive(); } void ToFImageGrabber::SetCameraDevice(ToFCameraDevice* aToFCameraDevice) { m_ToFCameraDevice = aToFCameraDevice; itk::SimpleMemberCommand::Pointer modifiedCommand = itk::SimpleMemberCommand::New(); modifiedCommand->SetCallbackFunction(this, &ToFImageGrabber::OnToFCameraDeviceModified); m_DeviceObserverTag = m_ToFCameraDevice->AddObserver(itk::ModifiedEvent(), modifiedCommand); this->Modified(); } ToFCameraDevice* ToFImageGrabber::GetCameraDevice() { return m_ToFCameraDevice; } int ToFImageGrabber::GetCaptureWidth() { return m_CaptureWidth; } int ToFImageGrabber::GetCaptureHeight() { return m_CaptureHeight; } int ToFImageGrabber::GetPixelNumber() { return m_PixelNumber; } int ToFImageGrabber::SetModulationFrequency(int modulationFrequency) { this->m_ToFCameraDevice->SetProperty("ModulationFrequency",mitk::IntProperty::New(modulationFrequency)); this->Modified(); return modulationFrequency; } int ToFImageGrabber::SetIntegrationTime(int integrationTime) { this->m_ToFCameraDevice->SetProperty("IntegrationTime",mitk::IntProperty::New(integrationTime)); this->Modified(); return integrationTime; } int ToFImageGrabber::GetIntegrationTime() { int integrationTime = 0; - BaseProperty* property = this->m_ToFCameraDevice->GetProperty("IntegrationTime"); - this->m_ToFCameraDevice->GetIntProperty(property,integrationTime); + this->m_ToFCameraDevice->GetIntProperty("IntegrationTime",integrationTime); return integrationTime; } int ToFImageGrabber::GetModulationFrequency() { int modulationFrequency = 0; - BaseProperty* property = this->m_ToFCameraDevice->GetProperty("ModulationFrequency"); - this->m_ToFCameraDevice->GetIntProperty(property,modulationFrequency); + this->m_ToFCameraDevice->GetIntProperty("ModulationFrequency",modulationFrequency); return modulationFrequency; } void ToFImageGrabber::SetBoolProperty( const char* propertyKey, bool boolValue ) { SetProperty(propertyKey, mitk::BoolProperty::New(boolValue)); } void ToFImageGrabber::SetIntProperty( const char* propertyKey, int intValue ) { SetProperty(propertyKey, mitk::IntProperty::New(intValue)); } void ToFImageGrabber::SetFloatProperty( const char* propertyKey, float floatValue ) { SetProperty(propertyKey, mitk::FloatProperty::New(floatValue)); } void ToFImageGrabber::SetStringProperty( const char* propertyKey, const char* stringValue ) { SetProperty(propertyKey, mitk::StringProperty::New(stringValue)); } void ToFImageGrabber::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { this->m_ToFCameraDevice->SetProperty(propertyKey, propertyValue); } void ToFImageGrabber::OnToFCameraDeviceModified() { this->Modified(); } void ToFImageGrabber::CleanUpImageArrays() { // free buffer if (m_IntensityArray) { delete [] m_IntensityArray; m_IntensityArray = NULL; } if (m_DistanceArray) { delete [] m_DistanceArray; m_DistanceArray = NULL; } if (m_AmplitudeArray) { delete [] m_AmplitudeArray; m_AmplitudeArray = NULL; } if (m_SourceDataArray) { delete [] m_SourceDataArray; m_SourceDataArray = NULL; } + if (m_RgbDataArray) + { + delete [] m_RgbDataArray; + m_RgbDataArray = NULL; + } } void ToFImageGrabber::AllocateImageArrays() { // cleanup memory if necessary this->CleanUpImageArrays(); // allocate buffer m_IntensityArray = new float[m_PixelNumber]; m_DistanceArray = new float[m_PixelNumber]; m_AmplitudeArray = new float[m_PixelNumber]; m_SourceDataArray = new char[m_SourceDataSize]; + m_RgbDataArray = new unsigned char[m_PixelNumber*3]; } } diff --git a/Modules/ToFHardware/mitkToFImageGrabber.h b/Modules/ToFHardware/mitkToFImageGrabber.h index a0ccfe395e..71af0d0802 100644 --- a/Modules/ToFHardware/mitkToFImageGrabber.h +++ b/Modules/ToFHardware/mitkToFImageGrabber.h @@ -1,170 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFImageGrabber_h #define __mitkToFImageGrabber_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkImageSource.h" #include "mitkToFCameraDevice.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /**Documentation * \brief Image source providing ToF images. Interface for filters provided in ToFProcessing module * * This class internally holds a ToFCameraDevice to access the images acquired by a ToF camera. * * Provided images include: distance image (output 0), amplitude image (output 1), intensity image (output 2) * * \ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFImageGrabber : public mitk::ImageSource { public: mitkClassMacro( ToFImageGrabber , ImageSource ); itkNewMacro( Self ); /*! \brief Establish a connection to the ToF camera \param device specifies the actually used ToF Camera. 0: PMD O3D, 1: PMD CamCube 2.0 */ virtual bool ConnectCamera(); /*! \brief Disconnects the ToF camera */ virtual bool DisconnectCamera(); /*! \brief Starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief Stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief Returns true if the camera is connected and started */ virtual bool IsCameraActive(); /*! \brief Sets the ToF device, the image grabber is grabbing the images from \param aToFCameraDevice device internally used for grabbing the images from the camera */ void SetCameraDevice(ToFCameraDevice* aToFCameraDevice); /*! \brief Get the currently set ToF camera device \return device currently used for grabbing images from the camera */ ToFCameraDevice* GetCameraDevice(); /*! \brief Set the modulation frequency used by the ToF camera. For default values see the corresponding device classes \param modulationFrequency modulation frequency in Hz */ int SetModulationFrequency(int modulationFrequency); /*! \brief Get the modulation frequency used by the ToF camera. \return modulation frequency in MHz */ int GetModulationFrequency(); /*! \brief Set the integration time used by the ToF camera. For default values see the corresponding device classes \param integrationTime integration time in ms */ int SetIntegrationTime(int integrationTime); /*! \brief Get the integration time in used by the ToF camera. \return integration time in ms */ int GetIntegrationTime(); /*! \brief Get the dimension in x direction of the ToF image \return width of the image */ int GetCaptureWidth(); /*! \brief Get the dimension in y direction of the ToF image \return height of the image */ int GetCaptureHeight(); /*! \brief Get the number of pixel in the ToF image \return number of pixel */ int GetPixelNumber(); // properties void SetBoolProperty( const char* propertyKey, bool boolValue ); void SetIntProperty( const char* propertyKey, int intValue ); void SetFloatProperty( const char* propertyKey, float floatValue ); void SetStringProperty( const char* propertyKey, const char* stringValue ); void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: /// /// called when the ToFCameraDevice was modified /// void OnToFCameraDeviceModified(); /*! \brief clean up memory allocated for the image arrays m_IntensityArray, m_DistanceArray, m_AmplitudeArray and m_SourceDataArray */ virtual void CleanUpImageArrays(); /*! \brief Allocate memory for the image arrays m_IntensityArray, m_DistanceArray, m_AmplitudeArray and m_SourceDataArray */ virtual void AllocateImageArrays(); ToFCameraDevice::Pointer m_ToFCameraDevice; ///< Device allowing acces to ToF image data int m_CaptureWidth; ///< Width of the captured ToF image int m_CaptureHeight; ///< Height of the captured ToF image int m_PixelNumber; ///< Number of pixels in the image int m_ImageSequence; ///< counter for currently acquired images int m_SourceDataSize; ///< size of the source data in bytes float* m_IntensityArray; ///< member holding the current intensity array float* m_DistanceArray; ///< member holding the current distance array float* m_AmplitudeArray; ///< member holding the current amplitude array char* m_SourceDataArray;///< member holding the current source data array + unsigned char* m_RgbDataArray; ///< member holding the current rgb data array unsigned long m_DeviceObserverTag; ///< tag of the oberver for the the ToFCameraDevice ToFImageGrabber(); ~ToFImageGrabber(); /*! \brief Method generating the outputs of this filter. Called in the updated process of the pipeline. 0: distance image 1: amplitude image 2: intensity image */ void GenerateData(); private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFImageRecorder.cpp b/Modules/ToFHardware/mitkToFImageRecorder.cpp index 2c64145e93..dde3618564 100644 --- a/Modules/ToFHardware/mitkToFImageRecorder.cpp +++ b/Modules/ToFHardware/mitkToFImageRecorder.cpp @@ -1,247 +1,252 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFImageRecorder.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include #pragma GCC visibility push(default) #include #pragma GCC visibility pop namespace mitk { ToFImageRecorder::ToFImageRecorder() { this->m_ToFCameraDevice = NULL; this->m_MultiThreader = itk::MultiThreader::New(); this->m_AbortMutex = itk::FastMutexLock::New(); this->m_ThreadID = 0; this->m_NumOfFrames = 0; this->m_ToFImageWriter = NULL; this->m_DistanceImageSelected = true; this->m_AmplitudeImageSelected = true; this->m_IntensityImageSelected = true; + this->m_RGBImageSelected = true; this->m_Abort = true; this->m_CaptureWidth = 0; this->m_CaptureHeight = 0; this->m_FileFormat = ""; this->m_PixelNumber = 0; this->m_SourceDataSize = 0; this->m_ToFImageType = ToFImageWriter::ToFImageType3D; this->m_RecordMode = ToFImageRecorder::PerFrames; this->m_DistanceImageFileName = ""; this->m_AmplitudeImageFileName = ""; this->m_IntensityImageFileName = ""; + this->m_RGBImageFileName = ""; this->m_ImageSequence = 0; this->m_DistanceArray = NULL; this->m_AmplitudeArray = NULL; this->m_IntensityArray = NULL; + this->m_RGBArray = NULL; this->m_SourceDataArray = NULL; } ToFImageRecorder::~ToFImageRecorder() { delete[] m_DistanceArray; delete[] m_AmplitudeArray; delete[] m_IntensityArray; + delete[] m_RGBArray; delete[] m_SourceDataArray; } void ToFImageRecorder::StopRecording() { this->m_AbortMutex->Lock(); this->m_Abort = true; this->m_AbortMutex->Unlock(); } void ToFImageRecorder::StartRecording() { if (this->m_ToFCameraDevice.IsNull()) { throw std::invalid_argument("ToFCameraDevice is NULL."); return; } if (this->m_FileFormat.compare(".csv") == 0) { this->m_ToFImageWriter = ToFImageCsvWriter::New(); } else if(this->m_FileFormat.compare(".nrrd") == 0) { this->m_ToFImageWriter = ToFNrrdImageWriter::New(); this->m_ToFImageWriter->SetExtension(m_FileFormat); } - else if(this->m_FileFormat.compare(".pic") == 0) - { - this->m_ToFImageWriter = ToFPicImageWriter::New(); - this->m_ToFImageWriter->SetExtension(m_FileFormat); - } else { throw std::logic_error("No file format specified!"); } this->m_CaptureWidth = this->m_ToFCameraDevice->GetCaptureWidth(); this->m_CaptureHeight = this->m_ToFCameraDevice->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_SourceDataSize = this->m_ToFCameraDevice->GetSourceDataSize(); // allocate buffer if(m_IntensityArray == NULL) { this->m_IntensityArray = new float[m_PixelNumber]; } if(this->m_DistanceArray == NULL) { this->m_DistanceArray = new float[m_PixelNumber]; } if(this->m_AmplitudeArray == NULL) { this->m_AmplitudeArray = new float[m_PixelNumber]; } + if(this->m_RGBArray == NULL) + { + this->m_RGBArray = new unsigned char[m_PixelNumber*3]; + } if(this->m_SourceDataArray == NULL) { this->m_SourceDataArray = new char[m_SourceDataSize]; } this->m_ToFImageWriter->SetDistanceImageFileName(this->m_DistanceImageFileName); this->m_ToFImageWriter->SetAmplitudeImageFileName(this->m_AmplitudeImageFileName); this->m_ToFImageWriter->SetIntensityImageFileName(this->m_IntensityImageFileName); + this->m_ToFImageWriter->SetRGBImageFileName(this->m_RGBImageFileName); this->m_ToFImageWriter->SetCaptureWidth(this->m_CaptureWidth); this->m_ToFImageWriter->SetCaptureHeight(this->m_CaptureHeight); this->m_ToFImageWriter->SetToFImageType(this->m_ToFImageType); this->m_ToFImageWriter->SetDistanceImageSelected(this->m_DistanceImageSelected); this->m_ToFImageWriter->SetAmplitudeImageSelected(this->m_AmplitudeImageSelected); this->m_ToFImageWriter->SetIntensityImageSelected(this->m_IntensityImageSelected); + this->m_ToFImageWriter->SetRGBImageSelected(this->m_RGBImageSelected); this->m_ToFImageWriter->Open(); this->m_AbortMutex->Lock(); this->m_Abort = false; this->m_AbortMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->RecordData, this); } ITK_THREAD_RETURN_TYPE ToFImageRecorder::RecordData(void* pInfoStruct) { struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFImageRecorder* toFImageRecorder = (ToFImageRecorder*)pInfo->UserData; if (toFImageRecorder!=NULL) { ToFCameraDevice::Pointer toFCameraDevice = toFImageRecorder->GetCameraDevice(); mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); int n = 100; double t1 = 0; double t2 = 0; t1 = realTimeClock->GetCurrentStamp(); bool overflow = false; bool printStatus = false; int requiredImageSequence = 0; int numOfFramesRecorded = 0; bool abort = false; toFImageRecorder->m_AbortMutex->Lock(); abort = toFImageRecorder->m_Abort; toFImageRecorder->m_AbortMutex->Unlock(); while ( !abort ) { if ( ((toFImageRecorder->m_RecordMode == ToFImageRecorder::PerFrames) && (numOfFramesRecorded < toFImageRecorder->m_NumOfFrames)) || (toFImageRecorder->m_RecordMode == ToFImageRecorder::Infinite) ) { toFCameraDevice->GetAllImages(toFImageRecorder->m_DistanceArray, toFImageRecorder->m_AmplitudeArray, - toFImageRecorder->m_IntensityArray, toFImageRecorder->m_SourceDataArray, requiredImageSequence, toFImageRecorder->m_ImageSequence ); + toFImageRecorder->m_IntensityArray, toFImageRecorder->m_SourceDataArray, requiredImageSequence, toFImageRecorder->m_ImageSequence, toFImageRecorder->m_RGBArray ); if (toFImageRecorder->m_ImageSequence >= requiredImageSequence) { if (toFImageRecorder->m_ImageSequence > requiredImageSequence) { MITK_INFO << "Problem! required: " << requiredImageSequence << " captured: " << toFImageRecorder->m_ImageSequence; } requiredImageSequence = toFImageRecorder->m_ImageSequence + 1; toFImageRecorder->m_ToFImageWriter->Add( toFImageRecorder->m_DistanceArray, - toFImageRecorder->m_AmplitudeArray, toFImageRecorder->m_IntensityArray ); + toFImageRecorder->m_AmplitudeArray, toFImageRecorder->m_IntensityArray, toFImageRecorder->m_RGBArray ); numOfFramesRecorded++; if (numOfFramesRecorded % n == 0) { printStatus = true; } if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFImageRecorder->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } toFImageRecorder->m_AbortMutex->Lock(); abort = toFImageRecorder->m_Abort; toFImageRecorder->m_AbortMutex->Unlock(); } else { abort = true; } } // end of while loop toFImageRecorder->InvokeEvent(itk::AbortEvent()); toFImageRecorder->m_ToFImageWriter->Close(); } return ITK_THREAD_RETURN_VALUE; } void ToFImageRecorder::SetCameraDevice(ToFCameraDevice* aToFCameraDevice) { this->m_ToFCameraDevice = aToFCameraDevice; } ToFCameraDevice* ToFImageRecorder::GetCameraDevice() { return this->m_ToFCameraDevice; } ToFImageWriter::ToFImageType ToFImageRecorder::GetToFImageType() { return this->m_ToFImageType; } void ToFImageRecorder::SetToFImageType(ToFImageWriter::ToFImageType toFImageType) { this->m_ToFImageType = toFImageType; } ToFImageRecorder::RecordMode ToFImageRecorder::GetRecordMode() { return this->m_RecordMode; } void ToFImageRecorder::SetRecordMode(ToFImageRecorder::RecordMode recordMode) { this->m_RecordMode = recordMode; } } diff --git a/Modules/ToFHardware/mitkToFImageRecorder.h b/Modules/ToFHardware/mitkToFImageRecorder.h index 3f09b6f76c..4cce490a4a 100644 --- a/Modules/ToFHardware/mitkToFImageRecorder.h +++ b/Modules/ToFHardware/mitkToFImageRecorder.h @@ -1,160 +1,166 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFImageRecorder_h #define __mitkToFImageRecorder_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" -#include "mitkToFPicImageWriter.h" #include "mitkToFImageCsvWriter.h" #include "mitkToFNrrdImageWriter.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkFastMutexLock.h" #include "itkCommand.h" namespace mitk { /** * @brief Recorder class for ToF images * * This class represents a recorder for ToF data. A ToFCameraDevice is used to acquire the data. The acquired images * are then added to a ToFImageWriter that performs the actual writing. * * Recording can be performed either frame-based or continuously * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFImageRecorder : public itk::Object { public: ToFImageRecorder(); ~ToFImageRecorder(); mitkClassMacro( ToFImageRecorder , itk::Object ); itkNewMacro( Self ); itkGetMacro( DistanceImageFileName, std::string ); itkGetMacro( AmplitudeImageFileName, std::string ); itkGetMacro( IntensityImageFileName, std::string ); + itkGetMacro( RGBImageFileName, std::string ); itkGetMacro( CaptureWidth, int ); itkGetMacro( CaptureHeight, int ); itkGetMacro( DistanceImageSelected, bool ); itkGetMacro( AmplitudeImageSelected, bool ); itkGetMacro( IntensityImageSelected, bool ); + itkGetMacro( RGBImageSelected, bool ); itkGetMacro( NumOfFrames, int ); itkGetMacro( FileFormat, std::string ); itkSetMacro( DistanceImageFileName, std::string ); itkSetMacro( AmplitudeImageFileName, std::string ); itkSetMacro( IntensityImageFileName, std::string ); + itkSetMacro(RGBImageFileName, std::string ); itkSetMacro( DistanceImageSelected, bool ); itkSetMacro( AmplitudeImageSelected, bool ); itkSetMacro( IntensityImageSelected, bool ); + itkSetMacro( RGBImageSelected, bool ); itkSetMacro( NumOfFrames, int ); itkSetMacro( FileFormat, std::string ); enum RecordMode{ PerFrames, Infinite }; /*! \brief Returns the currently set RecordMode \return record mode: PerFrames ("Record specified number of frames"), Infinite ("Record until abort is required") */ ToFImageRecorder::RecordMode GetRecordMode(); /*! \brief Set the RecordMode \param recordMode: PerFrames ("Record specified number of frames"), Infinite ("Record until abort is required") */ void SetRecordMode(ToFImageRecorder::RecordMode recordMode); /*! \brief Set the device used for acquiring ToF images \param aToFCameraDevice ToF camera device used. */ void SetCameraDevice(ToFCameraDevice* aToFCameraDevice); /*! \brief Get the device used for acquiring ToF images \return ToF camera device used. */ ToFCameraDevice* GetCameraDevice(); /*! \brief Get the type of image to be recorded \return ToF image type: ToFImageType3D (0) or ToFImageType2DPlusT (1) */ ToFImageWriter::ToFImageType GetToFImageType(); /*! \brief Set the type of image to be recorded \param toFImageType type of the ToF image: ToFImageType3D (0) or ToFImageType2DPlusT (1) */ void SetToFImageType(ToFImageWriter::ToFImageType toFImageType); /*! \brief Starts the recording by spawning a Thread which streams the data to a file. Aborting of the record process is controlled by the m_Abort flag */ void StartRecording(); /*! \brief Stops the recording by setting the m_Abort flag to false */ void StopRecording(); protected: /*! \brief Thread method acquiring data via the ToFCameraDevice and recording it to file via the ToFImageWriter */ static ITK_THREAD_RETURN_TYPE RecordData(void* pInfoStruct); // data acquisition ToFCameraDevice::Pointer m_ToFCameraDevice; ///< ToFCameraDevice used for acquiring the images int m_CaptureWidth; ///< width (x-dimension) of the images to record. int m_CaptureHeight; ///< height (y-dimension) of the images to record. int m_PixelNumber; ///< number of pixels (widht*height) of the images to record int m_SourceDataSize; ///< size of the source data provided by the device int m_ImageSequence; ///< number of images currently acquired float* m_IntensityArray; ///< array holding the intensity data float* m_DistanceArray; ///< array holding the distance data float* m_AmplitudeArray; ///< array holding the amplitude data + unsigned char* m_RGBArray; ///< array holding the RGB data if available (e.g. for Kinect) char* m_SourceDataArray; ///< array holding the source data // data writing ToFImageWriter::Pointer m_ToFImageWriter; ///< image writer writing the acquired images to a file std::string m_DistanceImageFileName; ///< file name for saving the distance image std::string m_AmplitudeImageFileName; ///< file name for saving the amplitude image std::string m_IntensityImageFileName; ///< file name for saving the intensity image - + std::string m_RGBImageFileName; ///< file name for saving the rgb image + int m_NumOfFrames; ///< number of frames to be recorded by this recorder ToFImageWriter::ToFImageType m_ToFImageType; ///< type of image to be recorded: ToFImageType3D (0) or ToFImageType2DPlusT (1) ToFImageRecorder::RecordMode m_RecordMode; ///< mode of recording the images: specified number of frames (PerFrames) or infinite (Infinite) std::string m_FileFormat; ///< file format for saving images. If .csv is chosen, ToFImageCsvWriter is used bool m_DistanceImageSelected; ///< flag indicating if distance image should be recorded bool m_AmplitudeImageSelected; ///< flag indicating if amplitude image should be recorded bool m_IntensityImageSelected; ///< flag indicating if intensity image should be recorded + bool m_RGBImageSelected; ///< flag indicating if rgb image should be recorded // threading itk::MultiThreader::Pointer m_MultiThreader; ///< member for thread-handling (ITK-based) int m_ThreadID; ///< ID of the thread recording the data itk::FastMutexLock::Pointer m_AbortMutex; ///< mutex for thread-safe data access of abort flag bool m_Abort; ///< flag controlling the abort mechanism of the recording procedure. For thread-safety only use in combination with m_AbortMutex private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFImageRecorderFilter.cpp b/Modules/ToFHardware/mitkToFImageRecorderFilter.cpp index 254a3a8f49..1d1a7b34c3 100644 --- a/Modules/ToFHardware/mitkToFImageRecorderFilter.cpp +++ b/Modules/ToFHardware/mitkToFImageRecorderFilter.cpp @@ -1,168 +1,163 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkToFNrrdImageWriter.h" -#include "mitkToFPicImageWriter.h" #include "mitkToFImageCsvWriter.h" // itk includes #include "itksys/SystemTools.hxx" mitk::ToFImageRecorderFilter::ToFImageRecorderFilter(): m_RecordingStarted(false), m_ToFImageWriter(0) { m_FileExtension = ""; } mitk::ToFImageRecorderFilter::~ToFImageRecorderFilter() { } void mitk::ToFImageRecorderFilter::SetFileName(std::string fileName) { std::string name = fileName; m_FileExtension = itksys::SystemTools::GetFilenameLastExtension( fileName ); if(m_FileExtension == ".nrrd") { m_ToFImageWriter = mitk::ToFNrrdImageWriter::New(); } - else if(m_FileExtension == ".pic") - { - m_ToFImageWriter = mitk::ToFPicImageWriter::New(); - } else if(m_FileExtension == ".csv") { m_ToFImageWriter = mitk::ToFImageCsvWriter::New(); } else { throw std::logic_error("The specified file type is not supported, standard file type is .nrrd!"); } int pos = name.find_last_of("."); name.insert(pos,"_DistanceImage"); m_ToFImageWriter->SetDistanceImageFileName(name); name = fileName; name.insert(pos,"_AmplitudeImage"); m_ToFImageWriter->SetAmplitudeImageFileName(name); name = fileName; name.insert(pos,"_IntensityImage"); m_ToFImageWriter->SetIntensityImageFileName(name); } void mitk::ToFImageRecorderFilter::SetImageType(mitk::ToFImageWriter::ToFImageType tofImageType) { m_ToFImageWriter->SetToFImageType(tofImageType); } void mitk::ToFImageRecorderFilter::GenerateData() { mitk::Image::Pointer distanceImageInput = this->GetInput(0); assert(distanceImageInput); mitk::Image::Pointer amplitudeImageInput = this->GetInput(1); assert(amplitudeImageInput); mitk::Image::Pointer intensityImageInput = this->GetInput(2); assert(intensityImageInput); // add current data to file stream float* distanceFloatData = (float*)distanceImageInput->GetSliceData(0, 0, 0)->GetData(); float* amplitudeFloatData = (float*)amplitudeImageInput->GetSliceData(0, 0, 0)->GetData(); float* intensityFloatData = (float*)intensityImageInput->GetSliceData(0, 0, 0)->GetData(); if (m_RecordingStarted) { m_ToFImageWriter->Add(distanceFloatData,amplitudeFloatData,intensityFloatData); } // set outputs to inputs this->SetNthOutput(0,distanceImageInput); this->SetNthOutput(1,amplitudeImageInput); this->SetNthOutput(2,intensityImageInput); } void mitk::ToFImageRecorderFilter::StartRecording() { if(m_ToFImageWriter.IsNull()) { throw std::logic_error("ToFImageWriter is unitialized, set filename first!"); return; } m_ToFImageWriter->Open(); m_RecordingStarted = true; } void mitk::ToFImageRecorderFilter::StopRecording() { m_ToFImageWriter->Close(); m_RecordingStarted = false; } mitk::ToFImageWriter::Pointer mitk::ToFImageRecorderFilter::GetToFImageWriter() { return m_ToFImageWriter; } void mitk::ToFImageRecorderFilter::SetToFImageWriter(mitk::ToFImageWriter::Pointer tofImageWriter) { m_ToFImageWriter = tofImageWriter; } void mitk::ToFImageRecorderFilter::SetInput( mitk::Image* input ) { this->SetInput(0,input); } void mitk::ToFImageRecorderFilter::SetInput( unsigned int idx, mitk::Image* input ) { if ((input == NULL) && (idx == this->GetNumberOfInputs() - 1)) // if the last input is set to NULL, reduce the number of inputs by one { this->SetNumberOfInputs(this->GetNumberOfInputs() - 1); } else { this->ProcessObject::SetNthInput(idx, input); // Process object is not const-correct so the const_cast is required here unsigned int xDim = input->GetDimension(0); unsigned int yDim = input->GetDimension(1); m_ToFImageWriter->SetCaptureWidth(xDim); m_ToFImageWriter->SetCaptureWidth(yDim); } this->CreateOutputsForAllInputs(); } mitk::Image* mitk::ToFImageRecorderFilter::GetInput() { return this->GetInput(0); } mitk::Image* mitk::ToFImageRecorderFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast< mitk::Image*>(this->ProcessObject::GetInput(idx)); } void mitk::ToFImageRecorderFilter::CreateOutputsForAllInputs() { this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create outputs for all inputs for (unsigned int idx = 0; idx < this->GetNumberOfOutputs(); ++idx) if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } diff --git a/Modules/ToFHardware/mitkToFImageWriter.cpp b/Modules/ToFHardware/mitkToFImageWriter.cpp index e44513e6fd..cde6276aa2 100644 --- a/Modules/ToFHardware/mitkToFImageWriter.cpp +++ b/Modules/ToFHardware/mitkToFImageWriter.cpp @@ -1,65 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include // itk includes #include "itksys/SystemTools.hxx" namespace mitk { ToFImageWriter::ToFImageWriter():m_Extension(".nrrd"), - m_DistanceImageFileName(), m_AmplitudeImageFileName(), m_IntensityImageFileName(), + m_DistanceImageFileName(), m_AmplitudeImageFileName(), m_IntensityImageFileName(), m_RGBImageFileName(), m_NumOfFrames(0), m_DistanceImageSelected(true), m_AmplitudeImageSelected(true), - m_IntensityImageSelected(true),m_CaptureWidth(200),m_CaptureHeight(200), + m_IntensityImageSelected(true), m_RGBImageSelected(true), m_CaptureWidth(200),m_CaptureHeight(200), m_PixelNumber(0), m_ImageSizeInBytes(0), m_ToFImageType(ToFImageWriter::ToFImageType3D) { } ToFImageWriter::~ToFImageWriter() { } void ToFImageWriter::CheckForFileExtension(std::string& fileName) { std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( fileName ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( fileName ); if( extension.length() != 0 && extension != this->m_Extension) { MITK_ERROR << "Wrong file extension! The default extension is " << this->m_Extension.c_str() << ", currently the requested file extension is " << extension.c_str() <<"!"; this->m_Extension = extension; } size_t found = fileName.find( this->m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle) if( found == std::string::npos) { fileName.append(this->m_Extension); } } ToFImageWriter::ToFImageType ToFImageWriter::GetToFImageType() { return this->m_ToFImageType; } void ToFImageWriter::SetToFImageType(ToFImageWriter::ToFImageType toFImageType) { this->m_ToFImageType = toFImageType; } } // end namespace mitk diff --git a/Modules/ToFHardware/mitkToFImageWriter.h b/Modules/ToFHardware/mitkToFImageWriter.h index 5b01bfc83d..ccf139354b 100644 --- a/Modules/ToFHardware/mitkToFImageWriter.h +++ b/Modules/ToFHardware/mitkToFImageWriter.h @@ -1,122 +1,128 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFImageWriter_h #define __mitkToFImageWriter_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFImageGrabber.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /** * @brief Writer class for ToF images * * This writer class allows streaming of ToF data into a file. The .pic file format is used for writing the data. * Image information is included in the header of the pic file. * Writer can simultaneously save "distance", "intensity" and "amplitude" image. * Images can be written as 3D volume (ToFImageType::ToFImageType3D) or temporal image stack (ToFImageType::ToFImageType2DPlusT) * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFImageWriter : public itk::Object { public: ToFImageWriter(); ~ToFImageWriter(); mitkClassMacro( ToFImageWriter , itk::Object ); itkNewMacro( Self ); itkGetMacro( DistanceImageFileName, std::string ); itkGetMacro( AmplitudeImageFileName, std::string ); itkGetMacro( IntensityImageFileName, std::string ); + itkGetMacro( RGBImageFileName, std::string ); itkGetMacro( Extension, std::string ); itkGetMacro( CaptureWidth, int ); itkGetMacro( CaptureHeight, int ); itkGetMacro( DistanceImageSelected, bool ); itkGetMacro( AmplitudeImageSelected, bool ); itkGetMacro( IntensityImageSelected, bool ); + itkGetMacro( RGBImageSelected, bool ); itkSetMacro( DistanceImageFileName, std::string ); itkSetMacro( AmplitudeImageFileName, std::string ); itkSetMacro( IntensityImageFileName, std::string ); + itkSetMacro( RGBImageFileName, std::string ); itkSetMacro( Extension, std::string ); itkSetMacro( CaptureWidth, int ); itkSetMacro( CaptureHeight, int ); itkSetMacro( DistanceImageSelected, bool ); itkSetMacro( AmplitudeImageSelected, bool ); itkSetMacro( IntensityImageSelected, bool ); + itkSetMacro( RGBImageSelected, bool ); enum ToFImageType{ ToFImageType3D, ToFImageType2DPlusT }; /*! \brief Get the type of image to be written \return ToF image type: ToFImageType3D (0) or ToFImageType2DPlusT (1) */ ToFImageWriter::ToFImageType GetToFImageType(); /*! \brief Set the type of image to be written \param toFImageType type of the ToF image: ToFImageType3D (0) or ToFImageType2DPlusT (1) */ void SetToFImageType(ToFImageWriter::ToFImageType toFImageType); /*! \brief Open file(s) for writing */ virtual void Open(){}; /*! \brief Close file(s) add .pic header and write */ virtual void Close(){}; /*! \brief Add new data to file. */ - virtual void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData){}; + virtual void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData=0){}; protected: /*! \brief Checks file name if file extension exists. If not an error message is returned */ void CheckForFileExtension(std::string& fileName); // member variables std::string m_DistanceImageFileName; ///< file name for saving the distance image std::string m_AmplitudeImageFileName; ///< file name for saving the amplitude image std::string m_IntensityImageFileName; ///< file name for saving the intensity image + std::string m_RGBImageFileName; ///< file name for saving the RGB image std::string m_Extension; ///< file extension used for saving images int m_CaptureWidth; ///< width (x-dimension) of the images to record. int m_CaptureHeight; ///< height (y-dimension) of the images to record. int m_PixelNumber; ///< number of pixels (widht*height) of the images to record int m_ImageSizeInBytes; ///< size of the image to save in bytes int m_NumOfFrames; ///< number of frames written to the image. Used for pic header. ToFImageWriter::ToFImageType m_ToFImageType; ///< type of image to be recorded: ToFImageType3D (0) or ToFImageType2DPlusT (1) bool m_DistanceImageSelected; ///< flag indicating if distance image should be recorded bool m_AmplitudeImageSelected; ///< flag indicating if amplitude image should be recorded bool m_IntensityImageSelected; ///< flag indicating if intensity image should be recorded + bool m_RGBImageSelected; ///< flag indicating if RGB image should be recorded private: }; } //END mitk namespace #endif // __mitkToFImageWriter_h diff --git a/Modules/ToFHardware/mitkToFNrrdImageWriter.cpp b/Modules/ToFHardware/mitkToFNrrdImageWriter.cpp index 9fe767263b..864090dc7c 100644 --- a/Modules/ToFHardware/mitkToFNrrdImageWriter.cpp +++ b/Modules/ToFHardware/mitkToFNrrdImageWriter.cpp @@ -1,206 +1,251 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // mitk includes #include // itk includes #include "itksys/SystemTools.hxx" #include "itkNrrdImageIO.h" namespace mitk { ToFNrrdImageWriter::ToFNrrdImageWriter(): ToFImageWriter(), m_DistanceOutfile(), m_AmplitudeOutfile(), m_IntensityOutfile() { m_Extension = std::string(".nrrd"); } ToFNrrdImageWriter::~ToFNrrdImageWriter() { } void ToFNrrdImageWriter::Open() { this->CheckForFileExtension(this->m_DistanceImageFileName); this->CheckForFileExtension(this->m_AmplitudeImageFileName); this->CheckForFileExtension(this->m_IntensityImageFileName); + this->CheckForFileExtension(this->m_RGBImageFileName); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_ImageSizeInBytes = this->m_PixelNumber * sizeof(float); if (this->m_DistanceImageSelected) { this->OpenStreamFile( this->m_DistanceOutfile, this->m_DistanceImageFileName); } if (this->m_AmplitudeImageSelected) { this->OpenStreamFile(this->m_AmplitudeOutfile, this->m_AmplitudeImageFileName); } if (this->m_IntensityImageSelected) { this->OpenStreamFile(this->m_IntensityOutfile, this->m_IntensityImageFileName); } + if (this->m_RGBImageSelected) + { + this->OpenStreamFile(this->m_RGBOutfile, this->m_RGBImageFileName); + } this->m_NumOfFrames = 0; } void ToFNrrdImageWriter::Close() { if (this->m_DistanceImageSelected) { this->CloseStreamFile(this->m_DistanceOutfile, this->m_DistanceImageFileName); } if (this->m_AmplitudeImageSelected) { this->CloseStreamFile(this->m_AmplitudeOutfile, this->m_AmplitudeImageFileName); } if (this->m_IntensityImageSelected) { this->CloseStreamFile(this->m_IntensityOutfile, this->m_IntensityImageFileName); } + if (this->m_RGBImageSelected) + { + this->CloseStreamFile(this->m_RGBOutfile, this->m_RGBImageFileName); + } } - void ToFNrrdImageWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData) + void ToFNrrdImageWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData) { if (this->m_DistanceImageSelected) { this->m_DistanceOutfile.write( (char*) distanceFloatData, this->m_ImageSizeInBytes); } if (this->m_AmplitudeImageSelected) { this->m_AmplitudeOutfile.write( (char*)amplitudeFloatData, this->m_ImageSizeInBytes); } if (this->m_IntensityImageSelected) { this->m_IntensityOutfile.write(( char* )intensityFloatData, this->m_ImageSizeInBytes); } + if (this->m_RGBImageSelected) + { + this->m_RGBOutfile.write(( char* )rgbData, this->m_PixelNumber*3 * sizeof(unsigned char)); + } this->m_NumOfFrames++; } void ToFNrrdImageWriter::OpenStreamFile( std::ofstream &outfile, std::string outfileName ) { outfile.open(outfileName.c_str(), std::ofstream::binary); if(!outfile.is_open()) { MITK_ERROR << "Error opening outfile: " << outfileName; throw std::logic_error("Error opening outfile."); return; } } void ToFNrrdImageWriter::CloseStreamFile( std::ofstream &outfile, std::string fileName ) { if (this->m_NumOfFrames == 0) { outfile.close(); throw std::logic_error("File is empty."); return; } // flush the last data to the file and convert the stream data to nrrd file outfile.flush(); this->ConvertStreamToNrrdFormat( fileName ); outfile.close(); } void ToFNrrdImageWriter::ConvertStreamToNrrdFormat( std::string fileName ) { - - float* floatData = new float[this->m_PixelNumber]; - for(int i=0; im_PixelNumber; i++) - { - floatData[i] = i + 0.0; - } - Image::Pointer imageTemplate = Image::New(); int dimension ; unsigned int* dimensions; if(m_ToFImageType == ToFImageType2DPlusT) { dimension = 4; dimensions = new unsigned int[dimension]; dimensions[0] = this->m_CaptureWidth; dimensions[1] = this->m_CaptureHeight; dimensions[2] = 1; dimensions[3] = this->m_NumOfFrames; } else if( m_ToFImageType == ToFImageType3D) { dimension = 3; dimensions = new unsigned int[dimension]; dimensions[0] = this->m_CaptureWidth; dimensions[1] = this->m_CaptureHeight; dimensions[2] = this->m_NumOfFrames; } else { throw std::logic_error("No image type set, please choose between 2D+t and 3D!"); } + float* floatData; + unsigned char* rgbData; + if (fileName==this->m_RGBImageFileName) + { + rgbData = new unsigned char[this->m_PixelNumber*3]; + for(int i=0; im_PixelNumber*3; i++) + { + rgbData[i] = i + 0.0; + } + mitk::PixelType RGBType = MakePixelType, 3>(); + imageTemplate->Initialize( RGBType,dimension, dimensions, 1); + imageTemplate->SetSlice(rgbData, 0, 0, 0); + } + else + { + floatData = new float[this->m_PixelNumber]; + for(int i=0; im_PixelNumber; i++) + { + floatData[i] = i + 0.0; + } + mitk::PixelType FloatType = MakeScalarPixelType(); + imageTemplate->Initialize( FloatType,dimension, dimensions, 1); + imageTemplate->SetSlice(floatData, 0, 0, 0); + } - mitk::PixelType FloatType = MakeScalarPixelType(); - imageTemplate->Initialize( FloatType,dimension, dimensions, 1); - imageTemplate->SetSlice(floatData, 0, 0, 0); - - itk::NrrdImageIO::Pointer nrrdWriter = itk::NrrdImageIO::New(); nrrdWriter->SetNumberOfDimensions(dimension); nrrdWriter->SetPixelTypeInfo(imageTemplate->GetPixelType().GetTypeId()); if(imageTemplate->GetPixelType().GetNumberOfComponents() > 1) { nrrdWriter->SetNumberOfComponents(imageTemplate->GetPixelType().GetNumberOfComponents()); } itk::ImageIORegion ioRegion( dimension ); mitk::Vector3D spacing = imageTemplate->GetGeometry()->GetSpacing(); mitk::Point3D origin = imageTemplate->GetGeometry()->GetOrigin(); for(unsigned int i = 0; i < dimension; i++) { nrrdWriter->SetDimensions(i,dimensions[i]); nrrdWriter->SetSpacing(i,spacing[i]); nrrdWriter->SetOrigin(i,origin[i]); mitk::Vector3D direction; direction.Set_vnl_vector(imageTemplate->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); vnl_vector< double > axisDirection(dimension); for(unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction[j]/spacing[i]; } nrrdWriter->SetDirection( i, axisDirection ); ioRegion.SetSize(i, imageTemplate->GetLargestPossibleRegion().GetSize(i) ); ioRegion.SetIndex(i, imageTemplate->GetLargestPossibleRegion().GetIndex(i) ); } nrrdWriter->SetIORegion(ioRegion); nrrdWriter->SetFileName(fileName); nrrdWriter->SetUseStreamedWriting(true); std::ifstream stream(fileName.c_str(), std::ifstream::binary); - unsigned int size = this->m_PixelNumber * this->m_NumOfFrames; - unsigned int sizeInBytes = size * sizeof(float); - float* data = new float[size]; - stream.read((char*)data, sizeInBytes); - nrrdWriter->Write(data); - stream.close(); - - delete[] data; + if (fileName==m_RGBImageFileName) + { + unsigned int size = this->m_PixelNumber*3 * this->m_NumOfFrames; + unsigned int sizeInBytes = size * sizeof(unsigned char); + unsigned char* data = new unsigned char[size]; + stream.read((char*)data, sizeInBytes); + nrrdWriter->Write(data); + stream.close(); + delete[] data; + } + else + { + unsigned int size = this->m_PixelNumber * this->m_NumOfFrames; + unsigned int sizeInBytes = size * sizeof(float); + float* data = new float[size]; + stream.read((char*)data, sizeInBytes); + nrrdWriter->Write(data); + stream.close(); + delete[] data; + } + delete[] dimensions; - delete[] floatData; + if (fileName==m_RGBImageFileName) + { + delete[] rgbData; + } + else + { + delete[] floatData; + } } } // end namespace mitk diff --git a/Modules/ToFHardware/mitkToFNrrdImageWriter.h b/Modules/ToFHardware/mitkToFNrrdImageWriter.h index 5ef689bfcd..96aa8b2b58 100644 --- a/Modules/ToFHardware/mitkToFNrrdImageWriter.h +++ b/Modules/ToFHardware/mitkToFNrrdImageWriter.h @@ -1,79 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFNrrdImageWriter_h #define __mitkToFNrrdImageWriter_h #include "mitkToFHardwareExports.h" #include "mitkToFImageWriter.h" #include namespace mitk { /** * @brief Writer class for ToF nrrd images * * This writer class allows streaming of ToF data into a nrrd file. This class uses the itkNrrdImageIO class * Writer can simultaneously save "distance", "intensity" and "amplitude" image. * Images can be written as 3D volume (ToFImageType::ToFImageType3D) or temporal image stack (ToFImageType::ToFImageType2DPlusT) * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFNrrdImageWriter : public ToFImageWriter { public: mitkClassMacro( ToFNrrdImageWriter , ToFImageWriter ); itkNewMacro( Self ); /*! \brief Open file(s) for writing */ void Open(); /*! \brief Close file(s) add .pic header and write */ void Close(); /*! \brief Add new data to file. */ - void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData); + void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData, unsigned char* rgbData=0); protected: std::ofstream m_DistanceOutfile; ///< file for distance image std::ofstream m_AmplitudeOutfile; ///< file for amplitude image std::ofstream m_IntensityOutfile; ///< file for intensity image + std::ofstream m_RGBOutfile; ///< file for intensity image private: ToFNrrdImageWriter(); ~ToFNrrdImageWriter(); /*! \brief Open file by filename to gain write access to it. */ void OpenStreamFile(std::ofstream &outfile, std::string outfileName); /*! \brief Close file after work on it is finished. */ void CloseStreamFile(std::ofstream &outfile, std::string fileName); /*! \brief Write image information to the NrrdFile. */ void ConvertStreamToNrrdFormat( std::string fileName ); }; } //END mitk namespace #endif // __mitkToFNrrdImageWriter_h diff --git a/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp b/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp index 704f47e112..ab42edbac6 100644 --- a/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp +++ b/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp @@ -1,179 +1,180 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFOpenCVImageGrabber.h" // mitk includes #include "mitkImageDataItem.h" +#include #include "vtkSmartPointer.h" #include "vtkColorTransferFunction.h" #include "vtkFloatArray.h" namespace mitk { ToFOpenCVImageGrabber::ToFOpenCVImageGrabber() { m_CurrentOpenCVIntensityImage = NULL; m_CurrentOpenCVAmplitudeImage = NULL; m_CurrentOpenCVDistanceImage = NULL; m_ImageType = 0; m_ImageDepth = IPL_DEPTH_32F; m_ImageGrabber = NULL; } ToFOpenCVImageGrabber::~ToFOpenCVImageGrabber() { } cv::Mat ToFOpenCVImageGrabber::GetImage() { m_ImageGrabber->Update(); unsigned int numOfPixel = m_ImageGrabber->GetCaptureWidth()*m_ImageGrabber->GetCaptureHeight(); // copy current mitk images unsigned int dimensions[4]; dimensions[0] = this->m_ImageGrabber->GetCaptureWidth(); dimensions[1] = this->m_ImageGrabber->GetCaptureHeight(); dimensions[2] = 1; dimensions[3] = 1; // create single component float pixel type mitk::PixelType FloatType = MakeScalarPixelType(); mitk::Image::Pointer currentMITKIntensityImage = mitk::Image::New(); currentMITKIntensityImage->Initialize(FloatType, 2, dimensions); currentMITKIntensityImage->SetSlice((float*)m_ImageGrabber->GetOutput(2)->GetSliceData()->GetData(),0,0,0); mitk::Image::Pointer currentMITKAmplitudeImage = mitk::Image::New(); currentMITKAmplitudeImage->Initialize(FloatType, 2, dimensions); currentMITKAmplitudeImage->SetSlice((float*)m_ImageGrabber->GetOutput(1)->GetSliceData()->GetData(),0,0,0); mitk::Image::Pointer currentMITKDistanceImage = mitk::Image::New(); currentMITKDistanceImage->Initialize(FloatType, 2, dimensions); currentMITKDistanceImage->SetSlice((float*)m_ImageGrabber->GetOutput(0)->GetSliceData()->GetData(),0,0,0); // copy mitk images to OpenCV images if (m_ImageDepth==IPL_DEPTH_32F) { if (m_ImageType==1) { float* amplitudeFloatData = (float*)currentMITKAmplitudeImage->GetSliceData(0, 0, 0)->GetData(); memcpy(m_CurrentOpenCVAmplitudeImage->imageData,(unsigned char*)amplitudeFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVAmplitudeImage); return image; } else if (m_ImageType==2) { float* intensityFloatData = (float*)currentMITKIntensityImage->GetSliceData(0, 0, 0)->GetData(); memcpy(m_CurrentOpenCVIntensityImage->imageData,(unsigned char*)intensityFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVIntensityImage); return image; } else { float* distanceFloatData = (float*)currentMITKDistanceImage->GetSliceData(0, 0, 0)->GetData(); memcpy(m_CurrentOpenCVDistanceImage->imageData,(unsigned char*)distanceFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVDistanceImage); return image; } } else { if (m_ImageType==1) { this->MapScalars(currentMITKAmplitudeImage, m_CurrentOpenCVAmplitudeImage); cv::Mat image(m_CurrentOpenCVAmplitudeImage); return image; } else if (m_ImageType==2) { this->MapScalars(currentMITKIntensityImage, m_CurrentOpenCVIntensityImage); cv::Mat image(m_CurrentOpenCVIntensityImage); return image; } else { this->MapScalars(currentMITKDistanceImage, m_CurrentOpenCVDistanceImage); cv::Mat image(m_CurrentOpenCVDistanceImage); return image; } } } void ToFOpenCVImageGrabber::SetImageType(unsigned int imageType) { m_ImageType = imageType; } void ToFOpenCVImageGrabber::SetImageDepth(unsigned int imageDepth) { m_ImageDepth = imageDepth; } void ToFOpenCVImageGrabber::SetToFImageGrabber(ToFImageGrabber::Pointer imageGrabber) { m_ImageGrabber = imageGrabber; //initialize OpenCV images m_CurrentOpenCVIntensityImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); m_CurrentOpenCVAmplitudeImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); m_CurrentOpenCVDistanceImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); } ToFImageGrabber::Pointer ToFOpenCVImageGrabber::GetToFImageGrabber() { return m_ImageGrabber; } void ToFOpenCVImageGrabber::StartCapturing() { if (m_ImageGrabber.IsNotNull()) { m_ImageGrabber->ConnectCamera(); m_ImageGrabber->StartCamera(); } } void ToFOpenCVImageGrabber::StopCapturing() { if (m_ImageGrabber.IsNotNull()) { m_ImageGrabber->StopCamera(); m_ImageGrabber->DisconnectCamera(); } } void ToFOpenCVImageGrabber::MapScalars( mitk::Image::Pointer mitkImage, IplImage* openCVImage) { unsigned int numOfPixel = m_ImageGrabber->GetCaptureWidth()*m_ImageGrabber->GetCaptureHeight(); float* floatData = (float*)mitkImage->GetSliceData(0, 0, 0)->GetData(); vtkSmartPointer colorTransferFunction = vtkColorTransferFunction::New(); vtkSmartPointer floatArrayInt; floatArrayInt = vtkFloatArray::New(); floatArrayInt->Initialize(); floatArrayInt->SetArray(floatData, numOfPixel, 0); - mitk::ScalarType min = mitkImage->GetScalarValueMin(); - mitk::ScalarType max = mitkImage->GetScalarValueMaxNoRecompute(); + mitk::ScalarType min = mitkImage->GetStatistics()->GetScalarValueMin(); + mitk::ScalarType max = mitkImage->GetStatistics()->GetScalarValueMaxNoRecompute(); MITK_INFO<<"Minimum: "<RemoveAllPoints(); colorTransferFunction->AddRGBPoint(min, 0, 0, 0); colorTransferFunction->AddRGBPoint(max, 1, 1, 1); colorTransferFunction->SetColorSpaceToHSV(); //TODO other depth values colorTransferFunction->MapScalarsThroughTable(floatArrayInt, (unsigned char*)openCVImage->imageData, VTK_LUMINANCE); } } diff --git a/Modules/ToFHardware/mitkToFPicImageWriter.cpp b/Modules/ToFHardware/mitkToFPicImageWriter.cpp deleted file mode 100644 index 3ff34395b4..0000000000 --- a/Modules/ToFHardware/mitkToFPicImageWriter.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ -#include -#include -#include - -// deprecated support of mitkIpPic -#include - -// itk includes -#include "itksys/SystemTools.hxx" - -extern "C" -{ -size_t _mitkIpPicFWrite( const void *ptr, size_t size, size_t nitems, mitkIpPicFile_t stream); -} - -namespace mitk -{ - ToFPicImageWriter::ToFPicImageWriter(): ToFImageWriter(), m_DistanceOutfile(NULL), - m_AmplitudeOutfile(NULL), m_IntensityOutfile(NULL) - { - m_Extension = std::string(".pic"); - } - - ToFPicImageWriter::~ToFPicImageWriter() - { - } - - void ToFPicImageWriter::Open() - { - this->CheckForFileExtension(this->m_DistanceImageFileName); - this->CheckForFileExtension(this->m_AmplitudeImageFileName); - this->CheckForFileExtension(this->m_IntensityImageFileName); - - this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; - this->m_ImageSizeInBytes = this->m_PixelNumber * sizeof(float); - float* floatData = new float[this->m_PixelNumber]; - for(int i=0; im_PixelNumber; i++) - { - floatData[i] = i + 0.0; - } - - this->m_MitkImage = Image::New(); - unsigned int dimensions[4]; - dimensions[0] = this->m_CaptureWidth; - dimensions[1] = this->m_CaptureHeight; - - mitk::PixelType FloatType = MakeScalarPixelType(); - if (this->m_ToFImageType == ToFImageWriter::ToFImageType2DPlusT) - { - dimensions[2] = 1; - dimensions[3] = 2; - this->m_MitkImage->Initialize( FloatType, 4, dimensions, 1); - } - else - { - dimensions[2] = 2; - dimensions[3] = 1; - this->m_MitkImage->Initialize( FloatType, 3, dimensions, 1); - } - this->m_MitkImage->SetSlice(floatData, 0, 0, 0); - - mitkIpPicDescriptor* pic = mitkIpPicNew(); - CastToIpPicDescriptor( this->m_MitkImage, pic); - - if (this->m_DistanceImageSelected) - { - this->OpenPicFile(&(this->m_DistanceOutfile), this->m_DistanceImageFileName); - this->WritePicFileHeader(this->m_DistanceOutfile, pic); - } - if (this->m_AmplitudeImageSelected) - { - this->OpenPicFile(&(this->m_AmplitudeOutfile), this->m_AmplitudeImageFileName); - this->WritePicFileHeader(this->m_AmplitudeOutfile, pic); - } - if (this->m_IntensityImageSelected) - { - this->OpenPicFile(&(this->m_IntensityOutfile), this->m_IntensityImageFileName); - this->WritePicFileHeader(this->m_IntensityOutfile, pic); - } - this->m_NumOfFrames = 0; - delete[] floatData; - } - - void ToFPicImageWriter::Close() - { - if (this->m_DistanceImageSelected) - { - this->ClosePicFile(this->m_DistanceOutfile); - } - if (this->m_AmplitudeImageSelected) - { - this->ClosePicFile(this->m_AmplitudeOutfile); - } - if (this->m_IntensityImageSelected) - { - this->ClosePicFile(this->m_IntensityOutfile); - } - } - - void ToFPicImageWriter::Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData) - { - if (this->m_DistanceImageSelected) - { - fwrite( distanceFloatData, this->m_ImageSizeInBytes, 1, this->m_DistanceOutfile ); - } - if (this->m_AmplitudeImageSelected) - { - fwrite( amplitudeFloatData, this->m_ImageSizeInBytes, 1, this->m_AmplitudeOutfile ); - } - if (this->m_IntensityImageSelected) - { - fwrite( intensityFloatData, this->m_ImageSizeInBytes, 1, this->m_IntensityOutfile ); - } - this->m_NumOfFrames++; - } - - void ToFPicImageWriter::OpenPicFile(FILE** outfile,std::string outfileName) - { - (*outfile) = fopen( outfileName.c_str(), "w+b" ); - if( !outfile ) // if fopen_s was not successful! - { - MITK_ERROR << "Error opening outfile: " << outfileName; - throw std::logic_error("Error opening outfile."); - return; - } - } - - void ToFPicImageWriter::ClosePicFile(FILE* outfile) - { - if (this->m_NumOfFrames == 0) - { - fclose(outfile); - throw std::logic_error("File is empty."); - return; - } - this->ReplacePicFileHeader(outfile); - fclose(outfile); - } - - void ToFPicImageWriter::ReplacePicFileHeader(FILE* outfile) - { - mitkIpPicDescriptor* pic = mitkIpPicNew(); - CastToIpPicDescriptor( this->m_MitkImage, pic); - - if (this->m_ToFImageType == ToFImageWriter::ToFImageType2DPlusT) - { - pic->dim = 4; - pic->n[2] = 1; - pic->n[3] = this->m_NumOfFrames; - } - else - { - pic->dim = 3; - pic->n[2] = this->m_NumOfFrames; - pic->n[3] = 1; - } - - fseek ( outfile, 0, SEEK_SET ); - - this->WritePicFileHeader( outfile, pic ); - } - - void ToFPicImageWriter::WritePicFileHeader(FILE* outfile, mitkIpPicDescriptor* pic) - { - mitkIpUInt4_t len; - mitkIpUInt4_t tagsLen; - - tagsLen = _mitkIpPicTagsSize( pic->info->tags_head ); - len = tagsLen + 3 * sizeof(mitkIpUInt4_t) + pic->dim * sizeof(mitkIpUInt4_t); - /* write oufile */ - if( mitkIpPicEncryptionType(pic) == ' ' ) - mitkIpPicFWrite( mitkIpPicVERSION, 1, sizeof(mitkIpPicTag_t), outfile ); - else - mitkIpPicFWrite( pic->info->version, 1, sizeof(mitkIpPicTag_t), outfile ); - - mitkIpPicFWriteLE( &len, sizeof(mitkIpUInt4_t), 1, outfile ); - - mitkIpPicFWriteLE( &(pic->type), sizeof(mitkIpUInt4_t), 1, outfile ); - mitkIpPicFWriteLE( &(pic->bpe), sizeof(mitkIpUInt4_t), 1, outfile ); - mitkIpPicFWriteLE( &(pic->dim), sizeof(mitkIpUInt4_t), 1, outfile ); - - mitkIpPicFWriteLE( pic->n, sizeof(mitkIpUInt4_t), pic->dim, outfile ); - - _mitkIpPicWriteTags( pic->info->tags_head, outfile, mitkIpPicEncryptionType(pic) ); - pic->info->pixel_start_in_file = ftell( outfile ); - } - -} // end namespace mitk diff --git a/Modules/ToFHardware/mitkToFPicImageWriter.h b/Modules/ToFHardware/mitkToFPicImageWriter.h deleted file mode 100644 index c762e14106..0000000000 --- a/Modules/ToFHardware/mitkToFPicImageWriter.h +++ /dev/null @@ -1,89 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ -#ifndef __mitkToFPicImageWriter_h -#define __mitkToFPicImageWriter_h - -#include "mitkToFHardwareExports.h" -#include "mitkToFImageWriter.h" - -#include - -namespace mitk -{ - /** - * @brief Writer class for ToF images - * - * This writer class allows streaming of ToF data into a file. The .pic file format is used for writing the data. - * Image information is included in the header of the pic file. - * Writer can simultaneously save "distance", "intensity" and "amplitude" image. - * Images can be written as 3D volume (ToFImageType::ToFImageType3D) or temporal image stack (ToFImageType::ToFImageType2DPlusT) - * - * @ingroup ToFHardware - */ - class MITK_TOFHARDWARE_EXPORT ToFPicImageWriter : public ToFImageWriter - { - public: - - ToFPicImageWriter(); - - ~ToFPicImageWriter(); - - mitkClassMacro( ToFPicImageWriter , ToFImageWriter ); - itkNewMacro( Self ); - - /*! - \brief Open file(s) for writing - */ - void Open(); - /*! - \brief Close file(s) add .pic header and write - */ - void Close(); - /*! - \brief Add new data to file. - */ - void Add(float* distanceFloatData, float* amplitudeFloatData, float* intensityFloatData); - - protected: - - Image::Pointer m_MitkImage; ///< mitk image used for pic header creation - FILE* m_DistanceOutfile; ///< file for distance image - FILE* m_AmplitudeOutfile; ///< file for amplitude image - FILE* m_IntensityOutfile; ///< file for intensity image - - - private: - - /*! - \brief Open file by filename to gain write access to it. - */ - void OpenPicFile(FILE** outfile, std::string outfileName); - /*! - \brief Close file after work on it is finished. - */ - void ClosePicFile(FILE* outfile); - /*! - \brief Replace current PicFileHeader information. - */ - void ReplacePicFileHeader(FILE* outfile); - /*! - \brief Write image information to the PicFileHeader. - */ - void WritePicFileHeader(FILE* outfile, mitkIpPicDescriptor* pic); - - }; -} //END mitk namespace -#endif // __mitkToFPicImageWriter_h diff --git a/Modules/ToFProcessing/mitkToFTestingCommon.h b/Modules/ToFProcessing/mitkToFTestingCommon.h index 9f2d53ae20..a7ef8051ab 100644 --- a/Modules/ToFProcessing/mitkToFTestingCommon.h +++ b/Modules/ToFProcessing/mitkToFTestingCommon.h @@ -1,120 +1,135 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkToFTestingCOMMON_H #define mitkToFTestingCOMMON_H #include "mitkToFProcessingExports.h" #include "mitkVector.h" #include #include "mitkToFProcessingCommon.h" #include "mitkPicFileReader.h" #include #include #include #include #include #include #include namespace mitk { class mitkToFProcessing_EXPORT ToFTestingCommon { public: //creates a test image with given dimension filled with random values inline static mitk::Image::Pointer CreateTestImage(unsigned int dimX = 100, unsigned int dimY = 100) { typedef itk::Image ItkImageType2D; typedef itk::ImageRegionIterator ItkImageRegionIteratorType2D; ItkImageType2D::Pointer image = ItkImageType2D::New(); ItkImageType2D::IndexType start; start[0] = 0; start[1] = 0; ItkImageType2D::SizeType size; size[0] = dimX; size[1] = dimY; ItkImageType2D::RegionType region; region.SetSize(size); region.SetIndex( start); ItkImageType2D::SpacingType spacing; spacing[0] = 1.0; spacing[1] = 1.0; image->SetRegions( region ); image->SetSpacing ( spacing ); image->Allocate(); //Correlate inten values to PixelIndex// ItkImageRegionIteratorType2D imageIterator(image,image->GetLargestPossibleRegion()); imageIterator.GoToBegin(); itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randomGenerator = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); while (!imageIterator.IsAtEnd()) { double pixelValue = randomGenerator->GetUniformVariate(0.0,1000.0); imageIterator.Set(pixelValue); ++imageIterator; } mitk::Image::Pointer mitkImage = mitk::Image::New(); mitk::CastToMitkImage(image,mitkImage); return mitkImage; } //loads an image from file inline static mitk::Image::Pointer LoadImage( std::string filename ) { mitk::PicFileReader::Pointer reader = mitk::PicFileReader::New(); reader->SetFileName ( filename.c_str() ); reader->Update(); if ( reader->GetOutput() == NULL ) itkGenericExceptionMacro("File "<GetOutput(); return image; } //loads a surface from file inline static mitk::Surface::Pointer LoadSurface( std::string filename ) { mitk::STLFileReader::Pointer reader = mitk::STLFileReader::New(); reader->SetFileName( filename.c_str() ); reader->Update(); if ( reader->GetOutput() == NULL ) itkGenericExceptionMacro("File "<< filename <<" could not be read!"); mitk::Surface::Pointer surface = reader->GetOutput(); return surface; } inline static bool SaveImage( mitk::Image* data, std::string filename ) { std::string extension = itksys::SystemTools::GetFilenameLastExtension( filename ); if (extension == ".gz") { filename.assign( filename, 0, filename.length() - 7 ); // remove last 7 characters (.pic.gz) } else if (extension == ".pic") { filename.assign( filename, 0, filename.length() - 4 ); // remove last 4 characters } try { mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); imageWriter->SetInput(data); imageWriter->SetFileName(filename.c_str()); imageWriter->SetExtension(".pic.gz"); imageWriter->Write(); } catch ( std::exception& e ) { std::cerr << "Error during attempt to write '" << filename << "'.pic Exception says:" << std::endl; std::cerr << e.what() << std::endl; return false; } return true; } }; } #endif diff --git a/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.cpp b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.cpp new file mode 100644 index 0000000000..0f6c5314fd --- /dev/null +++ b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.cpp @@ -0,0 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +const std::string QmitkKinectParameterWidget::VIEW_ID = "org.mitk.views.qmitkkinectparameterwidget"; + +QmitkKinectParameterWidget::QmitkKinectParameterWidget(QWidget* p, Qt::WindowFlags f): QWidget(p, f) +{ + m_ToFImageGrabber = NULL; + m_Controls = NULL; + CreateQtPartControl(this); +} + +QmitkKinectParameterWidget::~QmitkKinectParameterWidget() +{ +} + +void QmitkKinectParameterWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkKinectParameterWidgetControls; + m_Controls->setupUi(parent); + + this->CreateConnections(); + } +} + +void QmitkKinectParameterWidget::CreateConnections() +{ + if ( m_Controls ) + { + connect( m_Controls->m_RGB, SIGNAL(toggled(bool)), this, SLOT(OnAcquisitionModeChanged()) ); + connect( m_Controls->m_IR, SIGNAL(toggled(bool)), this, SLOT(OnAcquisitionModeChanged()) ); + } +} + +mitk::ToFImageGrabber* QmitkKinectParameterWidget::GetToFImageGrabber() +{ + return this->m_ToFImageGrabber; +} + +void QmitkKinectParameterWidget::SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber) +{ + this->m_ToFImageGrabber = aToFImageGrabber; +} + +void QmitkKinectParameterWidget::ActivateAllParameters() +{ + this->OnAcquisitionModeChanged(); +} + +void QmitkKinectParameterWidget::OnAcquisitionModeChanged() +{ + if (m_ToFImageGrabber.IsNotNull()) + { + // stop camera if active + bool active = m_ToFImageGrabber->IsCameraActive(); + if (active) + { + m_ToFImageGrabber->StopCamera(); + m_ToFImageGrabber->DisconnectCamera(); + } + this->m_ToFImageGrabber->SetBoolProperty("RGB", m_Controls->m_RGB->isChecked()); + this->m_ToFImageGrabber->SetBoolProperty("IR", m_Controls->m_IR->isChecked()); + if (active) + { + m_ToFImageGrabber->ConnectCamera(); + m_ToFImageGrabber->StartCamera(); + } + } +} + diff --git a/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.h b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.h new file mode 100644 index 0000000000..789fc989ae --- /dev/null +++ b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidget.h @@ -0,0 +1,78 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _QMITKKINECTPARAMETERWIDGET_H_INCLUDED +#define _QMITKKINECTPARAMETERWIDGET_H_INCLUDED + +#include "mitkTOFUIExports.h" +#include "ui_QmitkKinectParameterWidgetControls.h" + +//mitk headers +#include + +#include + +/** +* @brief Widget for configuring the Kinect device +* +* @ingroup ToFUI +*/ +class mitkTOFUI_EXPORT QmitkKinectParameterWidget :public QWidget +{ + //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) + Q_OBJECT + + public: + + static const std::string VIEW_ID; + + QmitkKinectParameterWidget(QWidget* p = 0, Qt::WindowFlags f = 0); + virtual ~QmitkKinectParameterWidget(); + + /* @brief This method is part of the widget an needs not to be called seperately. */ + virtual void CreateQtPartControl(QWidget *parent); + /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ + virtual void CreateConnections(); + + /*! + \brief returns the ToFImageGrabber + \return ToFImageGrabber currently used by the widget + */ + mitk::ToFImageGrabber* GetToFImageGrabber(); + + /*! + \brief sets the ToFImageGrabber + */ + void SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber); + + /*! + \brief activate camera settings according to the parameters from GUI + */ + void ActivateAllParameters(); + + protected slots: + void OnAcquisitionModeChanged(); + + protected: + + Ui::QmitkKinectParameterWidgetControls* m_Controls; ///< member holding the UI elements of this widget + + mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< image grabber object to be configured by the widget + + private: +}; + +#endif // _QmitkKinectParameterWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkKinectParameterWidgetControls.ui b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidgetControls.ui new file mode 100644 index 0000000000..02ff87e5d0 --- /dev/null +++ b/Modules/ToFUI/Qmitk/QmitkKinectParameterWidgetControls.ui @@ -0,0 +1,73 @@ + + + QmitkKinectParameterWidgetControls + + + + 0 + 0 + 425 + 76 + + + + + 0 + 0 + + + + QmitkToFMESAParameter + + + + + + + 0 + 0 + + + + Kinect Camera Parameter + + + + + + Acquisition mode: + + + + + + + Acquire RGB and range image + + + RGB + + + true + + + + + + + Acquire infrared (IR) and range image + + + IR + + + + + + + + + + + + diff --git a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp index d5b510deeb..0c9bb8caaf 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp @@ -1,350 +1,344 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define _USE_MATH_DEFINES #include //QT headers #include #include #include //mitk headers #include "mitkToFConfig.h" #include "mitkToFCameraPMDCamCubeDevice.h" #include "mitkToFCameraPMDRawDataCamCubeDevice.h" #include "mitkToFCameraPMDCamBoardDevice.h" #include "mitkToFCameraPMDRawDataCamBoardDevice.h" #include "mitkToFCameraPMDO3Device.h" #include "mitkToFCameraPMDPlayerDevice.h" #include "mitkToFCameraPMDMITKPlayerDevice.h" #include "mitkToFCameraMITKPlayerDevice.h" #include "mitkToFCameraMESASR4000Device.h" +#include "mitkKinectDevice.h" //itk headers #include const std::string QmitkToFConnectionWidget::VIEW_ID = "org.mitk.views.qmitktofconnectionwidget"; QmitkToFConnectionWidget::QmitkToFConnectionWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_IntegrationTime = 0; this->m_ModulationFrequency = 0; this->m_ToFImageGrabber = mitk::ToFImageGrabber::New(); m_Controls = NULL; CreateQtPartControl(this); } QmitkToFConnectionWidget::~QmitkToFConnectionWidget() { } void QmitkToFConnectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFConnectionWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); // set available cameras to combo box QString string(MITK_TOF_CAMERAS); string.replace(";"," "); QStringList list = string.split(","); m_Controls->m_SelectCameraCombobox->addItems(list); ShowParameterWidget(); } } void QmitkToFConnectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ConnectCameraButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnConnectCamera()) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(currentIndexChanged(const QString)), this, SLOT(OnSelectCamera(const QString)) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(activated(const QString)), this, SLOT(OnSelectCamera(const QString)) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(activated(const QString)), this, SIGNAL(ToFCameraSelected(const QString)) ); } } void QmitkToFConnectionWidget::ShowParameterWidget() { QString selectedCamera = m_Controls->m_SelectCameraCombobox->currentText(); - if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| - (selectedCamera=="PMD CamBoardRaw")||(selectedCamera=="PMD CamCubeRaw") ) - { - ShowPMDParameterWidget(); - } - else if (selectedCamera=="MESA Swissranger 4000") - { - ShowMESAParameterWidget(); - } - else - { - this->m_Controls->m_PMDParameterWidget->hide(); - this->m_Controls->m_MESAParameterWidget->hide(); - } -} - -void QmitkToFConnectionWidget::ShowPMDParameterWidget() -{ - this->m_Controls->m_PMDParameterWidget->show(); - this->m_Controls->m_MESAParameterWidget->hide(); -} - -void QmitkToFConnectionWidget::ShowMESAParameterWidget() -{ - this->m_Controls->m_PMDParameterWidget->hide(); - this->m_Controls->m_MESAParameterWidget->show(); -} - -void QmitkToFConnectionWidget::ShowPlayerParameterWidget() -{ - this->m_Controls->m_PMDParameterWidget->hide(); - this->m_Controls->m_MESAParameterWidget->hide(); + this->OnSelectCamera(selectedCamera); } mitk::ToFImageGrabber* QmitkToFConnectionWidget::GetToFImageGrabber() { return m_ToFImageGrabber; } -void QmitkToFConnectionWidget::OnSelectCamera(const QString selectedText) +void QmitkToFConnectionWidget::OnSelectCamera(const QString selectedCamera) { - if (selectedText == "PMD CamCube 2.0/3.0" || selectedText == "PMD CamCubeRaw 2.0/3.0" ) // PMD camcube 2 - { - ShowPMDParameterWidget(); - } - else if (selectedText == "PMD CamBoard" || selectedText == "PMD CamBoardRaw" ) // pmd camboard - { - ShowPMDParameterWidget(); - } - else if (selectedText == "PMD O3D") // pmd O3d - { - ShowPMDParameterWidget(); - } - else if (selectedText == "MESA Swissranger 4000") // MESA 4000 + if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| + (selectedCamera=="PMD CamBoardRaw")||(selectedCamera=="PMD CamCubeRaw 2.0/3.0") ) { - ShowMESAParameterWidget(); + this->m_Controls->m_PMDParameterWidget->show(); + this->m_Controls->m_MESAParameterWidget->hide(); + this->m_Controls->m_KinectParameterWidget->hide(); } - else if (selectedText == "PMD Player") // pmd file player + else if (selectedCamera=="MESA Swissranger 4000") { - ShowPlayerParameterWidget(); + this->m_Controls->m_PMDParameterWidget->hide(); + this->m_Controls->m_MESAParameterWidget->show(); + this->m_Controls->m_KinectParameterWidget->hide(); } - else if (selectedText == "PMD Raw Data Player") // pmd raw data player + else if (selectedCamera=="Microsoft Kinect") { - ShowPlayerParameterWidget(); + this->m_Controls->m_PMDParameterWidget->hide(); + this->m_Controls->m_MESAParameterWidget->hide(); + this->m_Controls->m_KinectParameterWidget->show(); } - else if (selectedText == "MITK Player") // mitk player + else { - ShowPlayerParameterWidget(); + this->m_Controls->m_PMDParameterWidget->hide(); + this->m_Controls->m_MESAParameterWidget->hide(); + this->m_Controls->m_KinectParameterWidget->hide(); } } void QmitkToFConnectionWidget::OnConnectCamera() { bool playerMode = false; if (m_Controls->m_ConnectCameraButton->text()=="Connect") { //reset the status of the GUI buttons m_Controls->m_ConnectCameraButton->setEnabled(false); m_Controls->m_SelectCameraCombobox->setEnabled(false); //repaint the widget this->repaint(); QString tmpFileName(""); QString fileFilter(""); //select the camera to connect with QString selectedCamera = m_Controls->m_SelectCameraCombobox->currentText(); if (selectedCamera == "PMD CamCube 2.0/3.0") { //PMD CamCube this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDCamCubeDevice::New()); } else if (selectedCamera == "PMD CamCubeRaw 2.0/3.0") { //PMD CamCube this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataCamCubeDevice::New()); } else if (selectedCamera == "PMD CamBoard") { //PMD CamBoard this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDCamBoardDevice::New()); } else if (selectedCamera == "PMD CamBoardRaw") { //PMD CamBoard this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataCamBoardDevice::New()); } else if (selectedCamera == "PMD O3D") {//PMD O3 this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDO3Device::New()); } else if (selectedCamera == "MESA Swissranger 4000") {//MESA SR4000 this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraMESASR4000Device::New()); - } + } + else if (selectedCamera == "Microsoft Kinect") + {//KINECT + this->m_ToFImageGrabber->SetCameraDevice(mitk::KinectDevice::New()); + } else if (selectedCamera == "PMD Player") {//PMD player playerMode = true; fileFilter.append("PMD Files (*.pmd)"); this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDPlayerDevice::New()); } else if (selectedCamera == "PMD Raw Data Player") {//PMD MITK player playerMode = true; fileFilter.append("NRRD Images (*.nrrd);;PIC Images - deprecated (*.pic)"); this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataDevice::New()); } else if (selectedCamera == "MITK Player") {//MITK player playerMode = true; fileFilter.append("NRRD Images (*.nrrd);;PIC Images - deprecated (*.pic)"); this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraMITKPlayerDevice::New()); } // if a player was selected ... if (playerMode) { //... open a QFileDialog to chose the corresponding file from the disc tmpFileName = QFileDialog::getOpenFileName(NULL, "Play Image From...", "", fileFilter); if (tmpFileName.isEmpty()) { m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); QMessageBox::information( this, "Template functionality", "Please select a valid image before starting some action."); return; } if(selectedCamera == "PMD Player") { //set the PMD file name this->m_ToFImageGrabber->SetStringProperty("PMDFileName", tmpFileName.toStdString().c_str() ); } if (selectedCamera == "PMD Raw Data Player" || selectedCamera == "MITK Player") { std::string msg = ""; try { //get 3 corresponding file names std::string dir = itksys::SystemTools::GetFilenamePath( tmpFileName.toStdString() ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( tmpFileName.toStdString() ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( tmpFileName.toStdString() ); if (extension != ".pic" && extension != ".nrrd") { msg = msg + "Invalid file format, please select a \".nrrd\"-file"; throw std::logic_error(msg.c_str()); } int found = baseFilename.rfind("_DistanceImage"); if (found == std::string::npos) { found = baseFilename.rfind("_AmplitudeImage"); } if (found == std::string::npos) { found = baseFilename.rfind("_IntensityImage"); } if (found == std::string::npos) { - msg = msg + "Input file name must end with \"_DistanceImage.pic\", \"_AmplitudeImage.pic\" or \"_IntensityImage.pic\"!"; + found = baseFilename.rfind("_RGBImage"); + } + if (found == std::string::npos) + { + msg = msg + "Input file name must end with \"_DistanceImage\", \"_AmplitudeImage\", \"_IntensityImage\" or \"_RGBImage\"!"; throw std::logic_error(msg.c_str()); } std::string baseFilenamePrefix = baseFilename.substr(0,found); std::string distanceImageFileName = dir + "/" + baseFilenamePrefix + "_DistanceImage" + extension; std::string amplitudeImageFileName = dir + "/" + baseFilenamePrefix + "_AmplitudeImage" + extension; std::string intensityImageFileName = dir + "/" + baseFilenamePrefix + "_IntensityImage" + extension; + std::string rgbImageFileName = dir + "/" + baseFilenamePrefix + "_RGBImage" + extension; if (!itksys::SystemTools::FileExists(distanceImageFileName.c_str(), true)) { - msg = msg + "Inputfile not exist! " + distanceImageFileName; - throw std::logic_error(msg.c_str()); + this->m_ToFImageGrabber->SetStringProperty("DistanceImageFileName", ""); + } + else + { + this->m_ToFImageGrabber->SetStringProperty("DistanceImageFileName", distanceImageFileName.c_str()); } if (!itksys::SystemTools::FileExists(amplitudeImageFileName.c_str(), true)) { - msg = msg + "Inputfile not exist! " + amplitudeImageFileName; - throw std::logic_error(msg.c_str()); + this->m_ToFImageGrabber->SetStringProperty("AmplitudeImageFileName", ""); + } + else + { + this->m_ToFImageGrabber->SetStringProperty("AmplitudeImageFileName", amplitudeImageFileName.c_str()); } if (!itksys::SystemTools::FileExists(intensityImageFileName.c_str(), true)) { - msg = msg + "Inputfile not exist! " + intensityImageFileName; - throw std::logic_error(msg.c_str()); + this->m_ToFImageGrabber->SetStringProperty("IntensityImageFileName", ""); + } + else + { + this->m_ToFImageGrabber->SetStringProperty("IntensityImageFileName", intensityImageFileName.c_str()); + } + if (!itksys::SystemTools::FileExists(rgbImageFileName.c_str(), true)) + { + this->m_ToFImageGrabber->SetStringProperty("RGBImageFileName", ""); + } + else + { + this->m_ToFImageGrabber->SetStringProperty("RGBImageFileName", rgbImageFileName.c_str()); } - //set the file names - this->m_ToFImageGrabber->SetStringProperty("DistanceImageFileName", distanceImageFileName.c_str()); - this->m_ToFImageGrabber->SetStringProperty("AmplitudeImageFileName", amplitudeImageFileName.c_str()); - this->m_ToFImageGrabber->SetStringProperty("IntensityImageFileName", intensityImageFileName.c_str()); - } catch (std::exception &e) { MITK_ERROR << e.what(); QMessageBox::critical( this, "Error", e.what() ); m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); return; } } } - //if a connection could be established - if (this->m_ToFImageGrabber->ConnectCamera()) - { - this->m_Controls->m_PMDParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); - this->m_Controls->m_MESAParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); - if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| + this->m_Controls->m_PMDParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); + this->m_Controls->m_MESAParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); + this->m_Controls->m_KinectParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); + + if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| (selectedCamera=="PMD CamBoardRaw")||(selectedCamera=="PMD CamCubeRaw 2.0/3.0")) - { - this->m_Controls->m_PMDParameterWidget->ActivateAllParameters(); - } - else if (selectedCamera=="MESA Swissranger 4000") - { - this->m_Controls->m_MESAParameterWidget->ActivateAllParameters(); - } - m_Controls->m_ConnectCameraButton->setText("Disconnect"); + { + this->m_Controls->m_PMDParameterWidget->ActivateAllParameters(); + } + else if (selectedCamera=="MESA Swissranger 4000") + { + this->m_Controls->m_MESAParameterWidget->ActivateAllParameters(); + } + else if (selectedCamera=="Microsoft Kinect") + { + this->m_Controls->m_KinectParameterWidget->ActivateAllParameters(); + } + m_Controls->m_ConnectCameraButton->setText("Disconnect"); + //if a connection could be established + if (this->m_ToFImageGrabber->ConnectCamera()) + { // send connect signal to the caller functionality emit ToFCameraConnected(); } else { QMessageBox::critical( this, "Error", "Connection failed. Check if you have installed the latest driver for your system." ); m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); return; } m_Controls->m_ConnectCameraButton->setEnabled(true); } else if (m_Controls->m_ConnectCameraButton->text()=="Disconnect") { this->m_ToFImageGrabber->StopCamera(); this->m_ToFImageGrabber->DisconnectCamera(); m_Controls->m_ConnectCameraButton->setText("Connect"); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); // send disconnect signal to the caller functionality emit ToFCameraDisconnected(); } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h index e37f61abb9..44a546bb21 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h @@ -1,109 +1,104 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QMITKTOFCONNECTIONWIDGET_H_INCLUDED #define _QMITKTOFCONNECTIONWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFConnectionWidgetControls.h" //QT headers #include //mitk headers #include "mitkToFImageGrabber.h" /** * @brief Widget allowing to connect to different ToF / range cameras (located in module ToFProcessing) * * The widget basically allows to connect/disconnect to different ToF cameras * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFConnectionWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFConnectionWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFConnectionWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! \brief returns the ToFImageGrabber which was configured after selecting a camera / player \return ToFImageGrabber currently used by the widget */ mitk::ToFImageGrabber* GetToFImageGrabber(); signals: /*! \brief This signal is sent if the user has connected the TOF camera. * The ToFImageGrabber is now availiable if the method GetToFImageGrabber() is called. */ void ToFCameraConnected(); /*! \brief This signal is sent if the user has disconnect the TOF camera. */ void ToFCameraDisconnected(); /*! \brief signal that is emitted when a ToF camera is selected in the combo box */ void ToFCameraSelected(const QString selectedText); protected slots: /*! \brief slot called when the "Connect Camera" button was pressed * According to the selection in the camera combo box, the widget provides * the desired instance of the ToFImageGrabber */ void OnConnectCamera(); /*! \brief slot updating the GUI elements after the selection of the camera combo box has changed */ - void OnSelectCamera(const QString selectedText); + void OnSelectCamera(const QString selectedCamera); protected: Ui::QmitkToFConnectionWidgetControls* m_Controls; ///< member holding the UI elements of this widget mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< member holding the current ToFImageGrabber int m_IntegrationTime; ///< member for the current integration time of the ToF device int m_ModulationFrequency; ///< member for the current modulation frequency of the ToF device private: void ShowParameterWidget(); - void ShowPMDParameterWidget(); - - void ShowMESAParameterWidget(); - - void ShowPlayerParameterWidget(); }; #endif // _QMITKTOFCONNECTIONWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidgetControls.ui b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidgetControls.ui index d43807972c..6110dd201b 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidgetControls.ui +++ b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidgetControls.ui @@ -1,133 +1,142 @@ QmitkToFConnectionWidgetControls 0 0 405 - 124 + 139 0 0 QmitkToFConnection 11 ToF camera connection 0 0 0 50 10 -1 7 QComboBox::InsertAtBottom QComboBox::AdjustToContents true 0 50 10 Connect to camera Connect :/images/powerRed.png :/images/powerGreen.png:/images/powerRed.png 30 30 true + + + QmitkToFPMDParameterWidget QWidget
QmitkToFPMDParameterWidget.h
1
QmitkToFMESAParameterWidget QWidget
QmitkToFMESAParameterWidget.h
1
+ + QmitkKinectParameterWidget + QWidget +
QmitkKinectParameterWidget.h
+ 1 +
diff --git a/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.cpp index 57efe61547..ccac7fe49f 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.cpp @@ -1,396 +1,409 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define _USE_MATH_DEFINES #include "QmitkToFRecorderWidget.h" //QT headers #include #include #include #include #include #include //mitk headers #include //itk headers #pragma GCC visibility push(default) #include #pragma GCC visibility pop #include struct QFileDialogArgs; class QFileDialogPrivate; const std::string QmitkToFRecorderWidget::VIEW_ID = "org.mitk.views.qmitktofrecorderwidget"; QmitkToFRecorderWidget::QmitkToFRecorderWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_ToFImageRecorder = NULL; this->m_ToFImageGrabber = NULL; this->m_RecordMode = mitk::ToFImageRecorder::PerFrames; this-> m_Controls = NULL; CreateQtPartControl(this); } QmitkToFRecorderWidget::~QmitkToFRecorderWidget() { } void QmitkToFRecorderWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets this->m_Controls = new Ui::QmitkToFRecorderWidgetControls; this->m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkToFRecorderWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_PlayButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnPlay()) ); connect( (QObject*)(m_Controls->m_StopButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStop()) ); connect( (QObject*)(m_Controls->m_StartRecordingButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStartRecorder()) ); connect( (QObject*)(m_Controls->m_RecordModeComboBox), SIGNAL(currentIndexChanged(int)),(QObject*) this, SLOT(OnChangeRecordModeComboBox(int)) ); connect(this, SIGNAL(RecordingStopped()), this, SLOT(OnRecordingStopped()), Qt::BlockingQueuedConnection); } } void QmitkToFRecorderWidget::SetParameter(mitk::ToFImageGrabber* toFImageGrabber, mitk::ToFImageRecorder* toFImageRecorder) { this->m_ToFImageGrabber = toFImageGrabber; this->m_ToFImageRecorder = toFImageRecorder; this->m_StopRecordingCommand = CommandType::New(); this->m_StopRecordingCommand->SetCallbackFunction(this, &QmitkToFRecorderWidget::StopRecordingCallback); this->m_ToFImageRecorder->RemoveAllObservers(); this->m_ToFImageRecorder->AddObserver(itk::AbortEvent(), this->m_StopRecordingCommand); m_Controls->m_PlayButton->setChecked(false); m_Controls->m_PlayButton->setEnabled(true); m_Controls->m_StartRecordingButton->setChecked(false); m_Controls->m_RecorderGroupBox->setEnabled(true); } void QmitkToFRecorderWidget::StopRecordingCallback() { emit RecordingStopped(); } void QmitkToFRecorderWidget::ResetGUIToInitial() { m_Controls->m_PlayButton->setChecked(false); m_Controls->m_PlayButton->setEnabled(true); m_Controls->m_RecorderGroupBox->setEnabled(false); } void QmitkToFRecorderWidget::OnRecordingStopped() { m_Controls->m_StartRecordingButton->setChecked(false); m_Controls->m_RecorderGroupBox->setEnabled(true); } void QmitkToFRecorderWidget::OnStop() { StopCamera(); StopRecorder(); ResetGUIToInitial(); emit ToFCameraStopped(); } void QmitkToFRecorderWidget::OnPlay() { m_Controls->m_PlayButton->setChecked(true); m_Controls->m_PlayButton->setEnabled(false); m_Controls->m_RecorderGroupBox->setEnabled(true); this->repaint(); StartCamera(); emit ToFCameraStarted(); } void QmitkToFRecorderWidget::StartCamera() { bool ok = false; if (!m_ToFImageGrabber->IsCameraActive()) { m_ToFImageGrabber->StartCamera(); } } void QmitkToFRecorderWidget::StopCamera() { if( m_ToFImageGrabber.IsNotNull() ) m_ToFImageGrabber->StopCamera(); } void QmitkToFRecorderWidget::StopRecorder() { if( m_ToFImageRecorder.IsNotNull() ) { this->m_ToFImageRecorder->StopRecording(); } } void QmitkToFRecorderWidget::OnStartRecorder() { m_Controls->m_StartRecordingButton->setChecked(true); m_Controls->m_RecorderGroupBox->setEnabled(false); this->repaint(); int numOfFrames = m_Controls->m_NumOfFramesSpinBox->value(); try { bool fileOK = true; bool distanceImageSelected = true; bool amplitudeImageSelected = true; bool intensityImageSelected = true; + bool rgbImageSelected = true; bool rawDataSelected = false; QString tmpFileName(""); QString selectedFilter(""); QString imageFileName(""); mitk::ToFImageWriter::ToFImageType tofImageType; tmpFileName = QmitkToFRecorderWidget::getSaveFileName(tofImageType, - distanceImageSelected, amplitudeImageSelected, intensityImageSelected, rawDataSelected, + distanceImageSelected, amplitudeImageSelected, intensityImageSelected, rgbImageSelected, rawDataSelected, NULL, "Save Image To...", imageFileName, "NRRD Images (*.nrrd);;PIC Images - deprecated (*.pic);;Text (*.csv)", &selectedFilter); if (tmpFileName.isEmpty()) { fileOK = false; } else { imageFileName = tmpFileName; } if (fileOK) { std::string dir = itksys::SystemTools::GetFilenamePath( imageFileName.toStdString() ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( imageFileName.toStdString() ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( imageFileName.toStdString() ); int integrationTime = this->m_ToFImageGrabber->GetIntegrationTime(); int modulationFreq = this->m_ToFImageGrabber->GetModulationFrequency(); QString integrationTimeStr; integrationTimeStr.setNum(integrationTime); QString modulationFreqStr; modulationFreqStr.setNum(modulationFreq); QString numOfFramesStr(""); if (this->m_RecordMode == mitk::ToFImageRecorder::PerFrames) { numOfFramesStr.setNum(numOfFrames); } std::string distImageFileName = prepareFilename(dir, baseFilename, modulationFreqStr.toStdString(), integrationTimeStr.toStdString(), numOfFramesStr.toStdString(), extension, "_DistanceImage"); MITK_INFO << "Save distance data to: " << distImageFileName; std::string amplImageFileName = prepareFilename(dir, baseFilename, modulationFreqStr.toStdString(), integrationTimeStr.toStdString(), numOfFramesStr.toStdString(), extension, "_AmplitudeImage"); MITK_INFO << "Save amplitude data to: " << amplImageFileName; - std::string intenImageFileName = prepareFilename(dir, baseFilename, modulationFreqStr.toStdString(), + std::string intenImageFileName = prepareFilename(dir, baseFilename, modulationFreqStr.toStdString(), integrationTimeStr.toStdString(), numOfFramesStr.toStdString(), extension, "_IntensityImage"); MITK_INFO << "Save intensity data to: " << intenImageFileName; + std::string rgbImageFileName = prepareFilename(dir, baseFilename, modulationFreqStr.toStdString(), + integrationTimeStr.toStdString(), numOfFramesStr.toStdString(), extension, "_RGBImage"); + MITK_INFO << "Save intensity data to: " << rgbImageFileName; + if (selectedFilter.compare("Text (*.csv)") == 0) { this->m_ToFImageRecorder->SetFileFormat(".csv"); } else if (selectedFilter.compare("PIC Images - deprecated (*.pic)") == 0) { //default this->m_ToFImageRecorder->SetFileFormat(".pic"); QMessageBox::warning(NULL, "Deprecated File Format!", "Please note that *.pic file format is deprecated and not longer supported! The suggested file format for images is *.nrrd!"); } else if (selectedFilter.compare("NRRD Images (*.nrrd)") == 0) { this->m_ToFImageRecorder->SetFileFormat(".nrrd"); } else { QMessageBox::warning(NULL, "Unsupported file format!", "Please specify one of the supported file formats *.nrrd, *.csv!"); return; } numOfFrames = m_Controls->m_NumOfFramesSpinBox->value(); this->m_ToFImageRecorder->SetDistanceImageFileName(distImageFileName); this->m_ToFImageRecorder->SetAmplitudeImageFileName(amplImageFileName); this->m_ToFImageRecorder->SetIntensityImageFileName(intenImageFileName); + this->m_ToFImageRecorder->SetRGBImageFileName(rgbImageFileName); this->m_ToFImageRecorder->SetToFImageType(tofImageType); this->m_ToFImageRecorder->SetDistanceImageSelected(distanceImageSelected); this->m_ToFImageRecorder->SetAmplitudeImageSelected(amplitudeImageSelected); this->m_ToFImageRecorder->SetIntensityImageSelected(intensityImageSelected); + this->m_ToFImageRecorder->SetRGBImageSelected(rgbImageSelected); this->m_ToFImageRecorder->SetRecordMode(this->m_RecordMode); this->m_ToFImageRecorder->SetNumOfFrames(numOfFrames); emit RecordingStarted(); this->m_ToFImageRecorder->StartRecording(); } else { this->OnRecordingStopped(); } } catch(std::exception& e) { QMessageBox::critical(NULL, "Error", QString(e.what())); this->OnRecordingStopped(); } } QString QmitkToFRecorderWidget::getSaveFileName(mitk::ToFImageWriter::ToFImageType& tofImageType, bool& distanceImageSelected, bool& amplitudeImageSelected, bool& intensityImageSelected, + bool& rgbImageSelected, bool& rawDataSelected, QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options ) { QString selectedFileName = ""; QComboBox* combo = new QComboBox; combo->addItem("3D"); combo->addItem("2D + t"); QHBoxLayout* checkBoxGroup = new QHBoxLayout(); QCheckBox* distanceImageCheckBox = new QCheckBox; distanceImageCheckBox->setText("Distance image"); distanceImageCheckBox->setChecked(true); QCheckBox* amplitudeImageCheckBox = new QCheckBox; amplitudeImageCheckBox->setText("Amplitude image"); amplitudeImageCheckBox->setChecked(true); QCheckBox* intensityImageCheckBox = new QCheckBox; intensityImageCheckBox->setText("Intensity image"); intensityImageCheckBox->setChecked(true); + QCheckBox* rgbImageCheckBox = new QCheckBox; + rgbImageCheckBox->setText("RGB image"); + rgbImageCheckBox->setChecked(true); QCheckBox* rawDataCheckBox = new QCheckBox; rawDataCheckBox->setText("Raw data"); rawDataCheckBox->setChecked(false); rawDataCheckBox->setEnabled(false); checkBoxGroup->addWidget(distanceImageCheckBox); checkBoxGroup->addWidget(amplitudeImageCheckBox); checkBoxGroup->addWidget(intensityImageCheckBox); + checkBoxGroup->addWidget(rgbImageCheckBox); checkBoxGroup->addWidget(rawDataCheckBox); QFileDialog* fileDialog = new QFileDialog(parent, caption, dir, filter); QLayout* layout = fileDialog->layout(); QGridLayout* gridbox = qobject_cast(layout); if (gridbox) { gridbox->addWidget(new QLabel("ToF-Image type:")); gridbox->addWidget(combo); int lastRow = gridbox->rowCount(); gridbox->addLayout(checkBoxGroup, lastRow, 0, 1, -1); } fileDialog->setLayout(gridbox); fileDialog->setAcceptMode(QFileDialog::AcceptSave); if (selectedFilter) { fileDialog->selectNameFilter(*selectedFilter); } if (fileDialog->exec() == QDialog::Accepted) { if (selectedFilter) { *selectedFilter = fileDialog->selectedFilter(); } if (combo->currentIndex() == 0) { tofImageType = mitk::ToFImageWriter::ToFImageType3D; } else { tofImageType = mitk::ToFImageWriter::ToFImageType2DPlusT; } distanceImageSelected = distanceImageCheckBox->isChecked(); amplitudeImageSelected = amplitudeImageCheckBox->isChecked(); intensityImageSelected = intensityImageCheckBox->isChecked(); + rgbImageSelected = rgbImageCheckBox->isChecked(); rawDataSelected = rawDataCheckBox->isChecked(); selectedFileName = fileDialog->selectedFiles().value(0); } delete fileDialog; return selectedFileName; } std::string QmitkToFRecorderWidget::prepareFilename(std::string dir, std::string baseFilename, std::string modulationFreq, std::string integrationTime, std::string numOfFrames, std::string extension, std::string imageType) { std::string filenName(""); filenName.append(dir); filenName.append("/"); filenName.append(baseFilename); filenName.append("_MF"); filenName.append(modulationFreq); filenName.append("_IT"); filenName.append(integrationTime); filenName.append("_"); filenName.append(numOfFrames); filenName.append("Images"); filenName.append(imageType); filenName.append(extension); return filenName; } void QmitkToFRecorderWidget::OnChangeRecordModeComboBox(int index) { if (index == 0) { this->m_RecordMode = mitk::ToFImageRecorder::PerFrames; m_Controls->m_NumOfFramesSpinBox->setEnabled(true); } else { this->m_RecordMode = mitk::ToFImageRecorder::Infinite; m_Controls->m_NumOfFramesSpinBox->setEnabled(false); } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.h b/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.h index 2d17e76314..4ba1048a28 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFRecorderWidget.h @@ -1,188 +1,189 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QMITKTOFRECORDERWIDGET_H_INCLUDED #define _QMITKTOFRECORDERWIDGET_H_INCLUDED #include #include //QT headers #include #include #include #include //itk headers #include "itkCommand.h" //mitk headers #include #include class QmitkStdMultiWidget; struct QFileDialogArgs; class QFileIconProvider; class QFileDialogPrivate; /** * @brief Widget allowing to play / record ToF data * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFRecorderWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFRecorderWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFRecorderWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! \brief Set the parameters used for this widget \param ToFImageGrabber image grabber providing images from a ToF device \param tofImageRecorder image recorder allowing to record ToF images */ void SetParameter(mitk::ToFImageGrabber* ToFImageGrabber, mitk::ToFImageRecorder* toFImageRecorder); /*! \brief resets the GUI elements to the initial state. Play button: enabled, Stop button: disabled, Recording box: disabled */ void ResetGUIToInitial(); signals: /*! \brief signal emitted when "Play" button is pressed */ void ToFCameraStarted(); /*! \brief signal emitted when "Stop" button is pressed */ void ToFCameraStopped(); /*! \brief signal emitted when recording is started */ void RecordingStarted(); /*! \brief signal emitted AbortEvent() in ToFImageRecorder is observed */ void RecordingStopped(); public slots: /*! \brief slot invoking to start the camera. Calls StartCamera() and emits ToFCameraStarted signal */ void OnPlay(); /*! \brief slot invoking to stop the camera and the recorder. Calls StopCamera() and StopRecorder and emits ToFCameraStarted signal. Resets GUI to initial state. */ void OnStop(); /*! \brief slot invoking to start the recording After letting the user chose a file location for the record, m_ImageRecorder->StartRecording() is inoved. */ void OnStartRecorder(); /*! \brief slot resetting the GUI elements of the recording box */ void OnRecordingStopped(); /*! \brief slot activating/deactivating "number of frames" spin box dependent on recording mode (PerFrame / Infinite) */ void OnChangeRecordModeComboBox(int index); protected: /*! \brief starts the camera by calling ToFImageGrabber::StartCamera() */ void StartCamera(); /*! \brief stops the camera by calling ToFImageGrabber::StopCamera() */ void StopCamera(); /*! \brief stops the recording by calling ToFImageRecorder::StopRecording() */ void StopRecorder(); /*! \brief emits RecordingStopped signal. */ void StopRecordingCallback(); /*! \brief adapted version of QFileDialog::getSaveFileName() The user is now asked to choose which images he wants to save (Distance and/or Intensity and/or Amplitude image) and which type the saved image should have (3D, 2D+t). */ static QString getSaveFileName(mitk::ToFImageWriter::ToFImageType& tofImageType, bool& distanceImageSelected, bool& amplitudeImageSelected, bool& intensityImageSelected, + bool& rgbImageSelected, bool& rawDataSelected, QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0 ); /*! \brief method creating a filename from the given information \param dir directory to save the file \param baseFilename base file name entered by the user \param modulationFreq modulation frequency of the camera \param integrationTime integration time of the camera \param numOfFrames number of frames recorded \param extension file extension \param imageType type of image (DistanceImage, IntensityImage, AmplitudeImage) \return dir+"/"+baseFilename+"_MF"+modulationFreq+"_IT"+integrationTime+"_"+numOfFrames+"Images"+imageType+extension */ std::string prepareFilename(std::string dir, std::string baseFilename, std::string modulationFreq, std::string integrationTime, std::string numOfFrames, std::string extension, std::string imageType); Ui::QmitkToFRecorderWidgetControls* m_Controls; ///< member holding the UI elements of this widget mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< member holding the ToFImageGrabber for acquiring ToF images mitk::ToFImageRecorder::Pointer m_ToFImageRecorder; ///< member holding the recorder for ToF images mitk::ToFImageRecorder::RecordMode m_RecordMode; ///< member holding the RecordMode of the recorder (PerFrame / Infinite) typedef itk::SimpleMemberCommand CommandType; CommandType::Pointer m_StopRecordingCommand; ///< itkCommand for abort of recording private: }; #endif // _QMITKTOFRECORDERWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.cpp index 2cb454e029..cbcea58a39 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.cpp @@ -1,359 +1,382 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkToFVisualisationSettingsWidget.h" +#include +#include +#include + //QT headers #include #include const std::string QmitkToFVisualisationSettingsWidget::VIEW_ID = "org.mitk.views.qmitktofvisualisationsettingswidget"; QmitkToFVisualisationSettingsWidget::QmitkToFVisualisationSettingsWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) , m_Controls(NULL) , m_RangeSliderMin(0) , m_RangeSliderMax(0) -, m_MitkDistanceImage(NULL) -, m_MitkAmplitudeImage(NULL) -, m_MitkIntensityImage(NULL) +, m_MitkDistanceImageNode(NULL) +, m_MitkAmplitudeImageNode(NULL) +, m_MitkIntensityImageNode(NULL) , m_Widget1ColorTransferFunction(NULL) , m_Widget2ColorTransferFunction(NULL) , m_Widget3ColorTransferFunction(NULL) , m_Widget1TransferFunctionType(1) , m_Widget2TransferFunctionType(0) , m_Widget3TransferFunctionType(0) { CreateQtPartControl(this); } QmitkToFVisualisationSettingsWidget::~QmitkToFVisualisationSettingsWidget() { } void QmitkToFVisualisationSettingsWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFVisualisationSettingsWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkToFVisualisationSettingsWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_SelectWidgetCombobox), SIGNAL(currentIndexChanged(int)),(QObject*) this, SLOT(OnWidgetSelected(int)) ); connect( (QObject*)(m_Controls->m_SelectTransferFunctionTypeCombobox), SIGNAL(currentIndexChanged(int)),(QObject*) this, SLOT(OnTransferFunctionTypeSelected(int)) ); connect( (QObject*)(m_Controls->m_TransferFunctionResetButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnTransferFunctionReset()) ); connect(m_Controls->m_XEditColor, SIGNAL(returnPressed()), this, SLOT(OnSetXValueColor())); connect(m_Controls->m_RangeSliderMaxEdit, SIGNAL(returnPressed()), this, SLOT(OnRangeSliderMaxChanged())); connect(m_Controls->m_RangeSliderMinEdit, SIGNAL(returnPressed()), this, SLOT(OnRangeSliderMinChanged())); connect(m_Controls->m_RangeSliderReset, SIGNAL(pressed()), this, SLOT(OnResetSlider())); connect(m_Controls->m_RangeSlider, SIGNAL(spanChanged(int, int) ),this, SLOT( OnSpanChanged(int , int ) )); QPlastiqueStyle *sliderStyle = new QPlastiqueStyle(); m_Controls->m_RangeSlider->setMaximum(2048); m_Controls->m_RangeSlider->setMinimum(-2048); m_Controls->m_RangeSlider->setHandleMovementMode(QxtSpanSlider::NoOverlapping); m_Controls->m_RangeSlider->setStyle(sliderStyle); m_Controls->m_ColorTransferFunctionCanvas->SetQLineEdits(m_Controls->m_XEditColor, 0); m_Controls->m_ColorTransferFunctionCanvas->SetTitle(""/*"Value -> Grayscale/Color"*/); } } void QmitkToFVisualisationSettingsWidget::OnSetXValueColor() { m_Controls->m_ColorTransferFunctionCanvas->SetX(m_Controls->m_XEditColor->text().toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkToFVisualisationSettingsWidget::OnRangeSliderMaxChanged() { m_Controls->m_RangeSlider->setMaximum(m_Controls->m_RangeSliderMaxEdit->text().toInt()); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::OnRangeSliderMinChanged() { m_Controls->m_RangeSlider->setMinimum(m_Controls->m_RangeSliderMinEdit->text().toInt()); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::OnSpanChanged(int /*lower*/, int /*upper*/) { UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::OnResetSlider() { m_Controls->m_RangeSlider->setUpperValue(m_RangeSliderMax); m_Controls->m_RangeSlider->setLowerValue(m_RangeSliderMin); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::UpdateRanges() { int lower = m_Controls->m_RangeSlider->lowerValue(); int upper = m_Controls->m_RangeSlider->upperValue(); m_Controls->m_ColorTransferFunctionCanvas->SetMin(lower); m_Controls->m_ColorTransferFunctionCanvas->SetMax(upper); } -void QmitkToFVisualisationSettingsWidget::Initialize(mitk::Image* distanceImage, mitk::Image* amplitudeImage, mitk::Image* intensityImage) +void QmitkToFVisualisationSettingsWidget::Initialize(mitk::DataNode* distanceImageNode, mitk::DataNode* amplitudeImageNode, mitk::DataNode* intensityImageNode) { - this->m_MitkDistanceImage = distanceImage; - this->m_MitkAmplitudeImage = amplitudeImage; - this->m_MitkIntensityImage = intensityImage; - - if (!m_MitkDistanceImage && !m_MitkAmplitudeImage && !m_MitkIntensityImage) + this->m_MitkDistanceImageNode = distanceImageNode; + this->m_MitkAmplitudeImageNode = amplitudeImageNode; + this->m_MitkIntensityImageNode = intensityImageNode; + + // Initialize transfer functions for image DataNodes such that: + // Widget1 (Distance): color from red (2nd min) to blue (max) + // Widget2 (Amplitude): grey value from black (2nd min) to white (max) + // Widget3 (Intensity): grey value from black (2nd min) to white (max) + if (!m_MitkDistanceImageNode && !m_MitkAmplitudeImageNode && !m_MitkIntensityImageNode) { m_Controls->m_ColorTransferFunctionCanvas->setEnabled(false); } else { m_Controls->m_ColorTransferFunctionCanvas->setEnabled(true); int numberOfImages = 0; - if (m_MitkDistanceImage) + if (m_MitkDistanceImageNode) { - m_RangeSliderMin = distanceImage->GetScalarValueMin(); - m_RangeSliderMax = distanceImage->GetScalarValueMax(); - m_Widget1ColorTransferFunction = vtkColorTransferFunction::New(); this->m_Widget1TransferFunctionType = 1; m_Controls->m_SelectTransferFunctionTypeCombobox->setCurrentIndex(this->m_Widget1TransferFunctionType); - ResetTransferFunction(this->m_Widget1ColorTransferFunction, this->m_Widget1TransferFunctionType ,distanceImage->GetScalarValueMin(), distanceImage->GetScalarValueMax()); - UpdateCanvas(); - - int border = (m_RangeSliderMax - m_RangeSliderMin) * 0.1; - m_Controls->m_RangeSlider->setMinimum(m_RangeSliderMin - border); - m_Controls->m_RangeSlider->setMaximum(m_RangeSliderMax + border); - m_Controls->m_RangeSliderMinEdit->setText(QString("").setNum(m_RangeSliderMin - border)); - m_Controls->m_RangeSliderMaxEdit->setText(QString("").setNum(m_RangeSliderMax + border)); - m_Controls->m_RangeSlider->setSpan( m_RangeSliderMin, m_RangeSliderMax); - - UpdateRanges(); numberOfImages++; } - if (m_MitkAmplitudeImage) + if (m_MitkAmplitudeImageNode) { m_Widget2ColorTransferFunction = vtkColorTransferFunction::New(); this->m_Widget2TransferFunctionType = 0; - ResetTransferFunction(this->m_Widget2ColorTransferFunction, this->m_Widget2TransferFunctionType, amplitudeImage->GetScalarValueMin(), amplitudeImage->GetScalarValueMax()); numberOfImages++; } - if (m_MitkIntensityImage) + if (m_MitkIntensityImageNode) { m_Widget3ColorTransferFunction = vtkColorTransferFunction::New(); this->m_Widget3TransferFunctionType = 0; - ResetTransferFunction(this->m_Widget3ColorTransferFunction, this->m_Widget3TransferFunctionType, intensityImage->GetScalarValueMin(), intensityImage->GetScalarValueMax()); numberOfImages++; } m_Controls->m_SelectWidgetCombobox->setMaxCount(numberOfImages); } + this->ReinitTransferFunction(0,1); + this->ReinitTransferFunction(1,0); + this->ReinitTransferFunction(2,0); } void QmitkToFVisualisationSettingsWidget::UpdateCanvas() { m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->GetSelectedColorTransferFunction() ); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::OnTransferFunctionTypeSelected(int index) { int currentWidgetIndex = m_Controls->m_SelectWidgetCombobox->currentIndex(); if (currentWidgetIndex == 0) { this->m_Widget1TransferFunctionType = index; } else if (currentWidgetIndex == 1) { this->m_Widget2TransferFunctionType = index; } else if (currentWidgetIndex == 2) { this->m_Widget3TransferFunctionType = index; } else { return; } } void QmitkToFVisualisationSettingsWidget::OnWidgetSelected(int index) { int currentWidgetIndex = m_Controls->m_SelectWidgetCombobox->currentIndex(); double valMin[6]; double valMax[6]; int numPoints; if (currentWidgetIndex == 0) { m_Controls->m_SelectTransferFunctionTypeCombobox->setCurrentIndex(this->m_Widget1TransferFunctionType); numPoints = this->m_Widget1ColorTransferFunction->GetSize(); this->m_Widget1ColorTransferFunction->GetNodeValue( 0, valMin ); this->m_Widget1ColorTransferFunction->GetNodeValue( numPoints-1, valMax ); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget1ColorTransferFunction ); } else if (currentWidgetIndex == 1) { m_Controls->m_SelectTransferFunctionTypeCombobox->setCurrentIndex(this->m_Widget2TransferFunctionType); numPoints = this->m_Widget2ColorTransferFunction->GetSize(); this->m_Widget2ColorTransferFunction->GetNodeValue( 0, valMin ); this->m_Widget2ColorTransferFunction->GetNodeValue( numPoints-1, valMax ); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget2ColorTransferFunction ); } else if (currentWidgetIndex == 2) { m_Controls->m_SelectTransferFunctionTypeCombobox->setCurrentIndex(this->m_Widget3TransferFunctionType); numPoints = this->m_Widget3ColorTransferFunction->GetSize(); this->m_Widget3ColorTransferFunction->GetNodeValue( 0, valMin ); this->m_Widget3ColorTransferFunction->GetNodeValue( numPoints-1, valMax ); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget3ColorTransferFunction ); } else if (currentWidgetIndex == 3) { } else { return; } m_RangeSliderMin = valMin[0]; m_RangeSliderMax = valMax[0]; int border = (m_RangeSliderMax - m_RangeSliderMin) * 0.1; m_Controls->m_RangeSlider->setMinimum(m_RangeSliderMin - border); m_Controls->m_RangeSlider->setMaximum(m_RangeSliderMax + border); m_Controls->m_RangeSliderMinEdit->setText(QString("").setNum(m_RangeSliderMin - border)); m_Controls->m_RangeSliderMaxEdit->setText(QString("").setNum(m_RangeSliderMax + border)); m_Controls->m_RangeSlider->setSpan( m_RangeSliderMin, m_RangeSliderMax); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } void QmitkToFVisualisationSettingsWidget::ResetTransferFunction(vtkColorTransferFunction* colorTransferFunction, int type, double min, double max) { colorTransferFunction->RemoveAllPoints(); if (type == 0) { colorTransferFunction->AddRGBPoint(min, 0, 0, 0); colorTransferFunction->AddRGBPoint(max, 1, 1, 1); } else { if (min>0.01) { colorTransferFunction->AddRGBPoint(0.0, 0, 0, 0); colorTransferFunction->AddRGBPoint(min-0.01, 0, 0, 0); } colorTransferFunction->AddRGBPoint(min, 1, 0, 0); colorTransferFunction->AddRGBPoint(min+(max-min)/2, 1, 1, 0); colorTransferFunction->AddRGBPoint(max, 0, 0, 1); } colorTransferFunction->SetColorSpaceToHSV(); } -void QmitkToFVisualisationSettingsWidget::OnTransferFunctionReset() +void QmitkToFVisualisationSettingsWidget::ReinitTransferFunction(int widget, int type) { - int currentTransferFunctionTypeIndex = m_Controls->m_SelectTransferFunctionTypeCombobox->currentIndex(); - int currentWidgetIndex = m_Controls->m_SelectWidgetCombobox->currentIndex(); - - if (currentWidgetIndex == 0) + switch (widget) + { + case 0: { + mitk::Image::Pointer distanceImage = dynamic_cast(m_MitkDistanceImageNode->GetData()); // use second minimum to draw 0 values (that are usually segmented) black - m_RangeSliderMin = this->m_MitkDistanceImage->GetScalarValue2ndMin(); - m_RangeSliderMax = this->m_MitkDistanceImage->GetScalarValueMaxNoRecompute(); - ResetTransferFunction(this->m_Widget1ColorTransferFunction, currentTransferFunctionTypeIndex, this->m_RangeSliderMin, this->m_RangeSliderMax); + m_RangeSliderMin = distanceImage->GetStatistics()->GetScalarValue2ndMin(); + m_RangeSliderMax = distanceImage->GetStatistics()->GetScalarValueMax(); + MITK_INFO<<"Distance Min: "<m_Widget1ColorTransferFunction, type, this->m_RangeSliderMin, this->m_RangeSliderMax); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget1ColorTransferFunction ); + mitk::TransferFunction::Pointer tf1 = mitk::TransferFunction::New(); + tf1->SetColorTransferFunction( m_Widget1ColorTransferFunction ); + m_MitkDistanceImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf1)); + break; } - else if (currentWidgetIndex == 1) + case 1: { - m_RangeSliderMin = this->m_MitkAmplitudeImage->GetScalarValueMin(); - m_RangeSliderMax = this->m_MitkAmplitudeImage->GetScalarValueMaxNoRecompute(); - ResetTransferFunction(this->m_Widget2ColorTransferFunction, currentTransferFunctionTypeIndex, this->m_RangeSliderMin, this->m_RangeSliderMax); + mitk::Image::Pointer amplitudeImage = dynamic_cast(m_MitkAmplitudeImageNode->GetData()); + m_RangeSliderMin = amplitudeImage->GetStatistics()->GetScalarValueMin(); + m_RangeSliderMax = amplitudeImage->GetStatistics()->GetScalarValueMax(); + MITK_INFO<<"Amplitude Min: "<m_Widget2ColorTransferFunction, type, this->m_RangeSliderMin, this->m_RangeSliderMax); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget2ColorTransferFunction ); + mitk::TransferFunction::Pointer tf2 = mitk::TransferFunction::New(); + tf2->SetColorTransferFunction( m_Widget2ColorTransferFunction ); + m_MitkAmplitudeImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf2)); + break; } - else if (currentWidgetIndex == 2) + case 2: { - m_RangeSliderMin = this->m_MitkIntensityImage->GetScalarValueMin(); - m_RangeSliderMax = this->m_MitkIntensityImage->GetScalarValueMaxNoRecompute(); - ResetTransferFunction(this->m_Widget3ColorTransferFunction, currentTransferFunctionTypeIndex, this->m_RangeSliderMin, this->m_RangeSliderMax); + mitk::Image::Pointer intensityImage = dynamic_cast(m_MitkIntensityImageNode->GetData()); + m_RangeSliderMin = intensityImage->GetStatistics()->GetScalarValueMin(); + m_RangeSliderMax = intensityImage->GetStatistics()->GetScalarValueMax(); + MITK_INFO<<"Intensity Min: "<m_Widget3ColorTransferFunction, type, this->m_RangeSliderMin, this->m_RangeSliderMax); m_Controls->m_ColorTransferFunctionCanvas->SetColorTransferFunction( this->m_Widget3ColorTransferFunction ); + mitk::TransferFunction::Pointer tf3 = mitk::TransferFunction::New(); + tf3->SetColorTransferFunction( m_Widget3ColorTransferFunction ); + m_MitkIntensityImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf3)); + break; } - else - { - return; + default: + break; } +} + +void QmitkToFVisualisationSettingsWidget::OnTransferFunctionReset() +{ + int currentTransferFunctionTypeIndex = m_Controls->m_SelectTransferFunctionTypeCombobox->currentIndex(); + int currentWidgetIndex = m_Controls->m_SelectWidgetCombobox->currentIndex(); + + this->ReinitTransferFunction(currentWidgetIndex,currentTransferFunctionTypeIndex); + int border = (m_RangeSliderMax - m_RangeSliderMin) * 0.1; m_Controls->m_RangeSlider->setMinimum(m_RangeSliderMin - border); m_Controls->m_RangeSlider->setMaximum(m_RangeSliderMax + border); m_Controls->m_RangeSliderMinEdit->setText(QString("").setNum(m_RangeSliderMin - border)); m_Controls->m_RangeSliderMaxEdit->setText(QString("").setNum(m_RangeSliderMax + border)); m_Controls->m_RangeSlider->setSpan( m_RangeSliderMin, m_RangeSliderMax); UpdateRanges(); m_Controls->m_ColorTransferFunctionCanvas->update(); } vtkColorTransferFunction* QmitkToFVisualisationSettingsWidget::GetWidget1ColorTransferFunction() { return this->m_Widget1ColorTransferFunction; } vtkColorTransferFunction* QmitkToFVisualisationSettingsWidget::GetWidget2ColorTransferFunction() { return this->m_Widget2ColorTransferFunction; } vtkColorTransferFunction* QmitkToFVisualisationSettingsWidget::GetWidget3ColorTransferFunction() { return this->m_Widget3ColorTransferFunction; } vtkColorTransferFunction* QmitkToFVisualisationSettingsWidget::GetSelectedColorTransferFunction() { int currentWidgetIndex = m_Controls->m_SelectWidgetCombobox->currentIndex(); if (currentWidgetIndex==0) { return this->m_Widget1ColorTransferFunction; } else if (currentWidgetIndex==1) { return this->m_Widget2ColorTransferFunction; } else if (currentWidgetIndex==2) { return this->m_Widget3ColorTransferFunction; } else { return this->m_Widget3ColorTransferFunction; } } int QmitkToFVisualisationSettingsWidget::GetSelectedImageIndex() { return this->m_Controls->m_SelectWidgetCombobox->currentIndex(); } diff --git a/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.h b/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.h index 5296777615..0454362bf3 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFVisualisationSettingsWidget.h @@ -1,159 +1,166 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QMITKTOFVISUALISATIONSETTINGSWIDGET_H_INCLUDED #define _QMITKTOFVISUALISATIONSETTINGSWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFVisualisationSettingsWidgetControls.h" +#include "mitkDataNode.h" // QT headers #include // vtk includes #include class QmitkStdMultiWidget; /** Documentation: * Widget controlling the visualization of Time-of-Flight image data. A color transfer function can be configured for * a given distance, amplitude and intensity image. The pre-configured vtkColorTransferFunctions can be accessed as * an output of the widget. * * \ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFVisualisationSettingsWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFVisualisationSettingsWidget (QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFVisualisationSettingsWidget (); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! \brief initialize the widget with the images to be shown \param distanceImage image holding the range image of a ToF camera \param amplitudeImage image holding the amplitude image of a ToF camera \param intensityImage image holding the intensity image of a ToF camera */ - void Initialize(mitk::Image* distanceImage=NULL, mitk::Image* amplitudeImage=NULL, mitk::Image* intensityImage=NULL); + void Initialize(mitk::DataNode* distanceImageNode=NULL, mitk::DataNode* amplitudeImageNode=NULL, mitk::DataNode* intensityImageNode=NULL); /*! \brief Access the color transfer function of widget 1 (distance image) \return vtkColorTransferFunction that can be used to define a TransferFunctionProperty */ vtkColorTransferFunction* GetWidget1ColorTransferFunction(); /*! \brief Access the color transfer function of widget 2 (distance image) \return vtkColorTransferFunction that can be used to define a TransferFunctionProperty */ vtkColorTransferFunction* GetWidget2ColorTransferFunction(); /*! \brief Access the color transfer function of widget 3 (distance image) \return vtkColorTransferFunction that can be used to define a TransferFunctionProperty */ vtkColorTransferFunction* GetWidget3ColorTransferFunction(); /*! \brief Access the color transfer of the currently selected widget \return vtkColorTransferFunction that can be used to define a TransferFunctionProperty */ vtkColorTransferFunction* GetSelectedColorTransferFunction(); /*! \brief Return the index of the selected image: 0 = Distance, 1 = Amplitude, 2 = Intensity */ int GetSelectedImageIndex(); protected slots: void OnSetXValueColor(); /*! \brief Slot invoking a reset of the RangeSlider to the minimal and maximal values of the according image */ void OnResetSlider(); /*! \brief Slot called when the range span has changed. */ void OnSpanChanged (int lower, int upper); /*! \brief Resets the transfer function according to the currently selected widget / image */ void OnTransferFunctionReset(); /*! \brief Updates the GUI according to the widget / image selection */ void OnWidgetSelected(int index); /*! \brief Slot called when the line edit of the maximal value of the range slider has changed. Leads to an update of the range slider. */ void OnRangeSliderMaxChanged(); /*! \brief Slot called when the line edit of the minimal value of the range slider has changed. Leads to an update of the range slider. */ void OnRangeSliderMinChanged(); /*! \brief Sets the TransferFunctionType members according to the selection of the widget and the transfer type. */ void OnTransferFunctionTypeSelected(int index); protected: /*! \brief Invokes an update of the ColorTransferFunctionCanvas. Called when the ColorTransferFunction has changed */ void UpdateCanvas(); /*! \brief Resets the ColorTransferFunctionCanvas according to the lower and upper value of the RangeSlider */ void UpdateRanges(); Ui::QmitkToFVisualisationSettingsWidgetControls* m_Controls; int m_RangeSliderMin; ///< Minimal value of the transfer function range. Initialized to the minimal value of the corresponding image. int m_RangeSliderMax; ///< Maximal value of the transfer function range. Initialized to the maximal value of the corresponding image. - mitk::Image::Pointer m_MitkDistanceImage; ///< Range image of the ToF camera as set by Initialize() - mitk::Image::Pointer m_MitkAmplitudeImage; ///< Amplitud image of the ToF camera as set by Initialize() - mitk::Image::Pointer m_MitkIntensityImage; ///< Intensity image of the ToF camera as set by Initialize() + mitk::DataNode::Pointer m_MitkDistanceImageNode; ///< DataNode holding the range image of the ToF camera as set by Initialize() + mitk::DataNode::Pointer m_MitkAmplitudeImageNode; ///< DataNode holding the amplitude image of the ToF camera as set by Initialize() + mitk::DataNode::Pointer m_MitkIntensityImageNode; ///< DataNode holding the intensity image of the ToF camera as set by Initialize() vtkColorTransferFunction* m_Widget1ColorTransferFunction; ///< vtkColorTransferFunction of widget 1 (distance) that can be used to define a TransferFunctionProperty vtkColorTransferFunction* m_Widget2ColorTransferFunction; ///< vtkColorTransferFunction of widget 2 (amplitude) that can be used to define a TransferFunctionProperty vtkColorTransferFunction* m_Widget3ColorTransferFunction; ///< vtkColorTransferFunction of widget 3 (intensity) that can be used to define a TransferFunctionProperty int m_Widget1TransferFunctionType; ///< member holding the type of the transfer function applied to the image shown in widget 1 (distance image): 0 = gray scale, 1 = color int m_Widget2TransferFunctionType; ///< member holding the type of the transfer function applied to the image shown in widget 2 (amplitude image): 0 = gray scale, 1 = color int m_Widget3TransferFunctionType; ///< member holding the type of the transfer function applied to the image shown in widget 3 (intensity image): 0 = gray scale, 1 = color private: /*! \brief Reset the color transfer function to the given type and range \param colorTransferFunction vtkColorTransferfunction to be resetted \param type type of the transfer function: 0 = gray scale, 1 = color \param min minimal value to be set to the transfer function \param max maximal value to be set to the transfer function */ void ResetTransferFunction(vtkColorTransferFunction* colorTransferFunction, int type, double min, double max); + /*! + \brief Reset the color transfer function for the given widget + \param widget 0: transversal, 1: coronal, 2: sagittal + \param type: type of the transfer function: 0 = gray scale, 1 = color + */ + void ReinitTransferFunction(int widget, int type); }; #endif // _QMITKTOFVISUALISATIONSETTINGSWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/files.cmake b/Modules/ToFUI/files.cmake index 084141cd52..c5dfc410c2 100644 --- a/Modules/ToFUI/files.cmake +++ b/Modules/ToFUI/files.cmake @@ -1,34 +1,36 @@ - -set(CPP_FILES +SET(CPP_FILES + Qmitk/QmitkKinectParameterWidget.cpp Qmitk/QmitkToFConnectionWidget.cpp Qmitk/QmitkToFPointSetWidget.cpp Qmitk/QmitkToFRecorderWidget.cpp Qmitk/QmitkToFVisualisationSettingsWidget.cpp Qmitk/QmitkToFCompositeFilterWidget.cpp Qmitk/QmitkToFPMDParameterWidget.cpp Qmitk/QmitkToFMESAParameterWidget.cpp ) -set(UI_FILES +SET(UI_FILES + Qmitk/QmitkKinectParameterWidgetControls.ui Qmitk/QmitkToFConnectionWidgetControls.ui Qmitk/QmitkToFPointSetWidgetControls.ui Qmitk/QmitkToFRecorderWidgetControls.ui Qmitk/QmitkToFVisualisationSettingsWidgetControls.ui Qmitk/QmitkToFCompositeFilterWidgetControls.ui Qmitk/QmitkToFPMDParameterWidgetControls.ui Qmitk/QmitkToFMESAParameterWidgetControls.ui ) -set(MOC_H_FILES +SET(MOC_H_FILES + Qmitk/QmitkKinectParameterWidget.h Qmitk/QmitkToFConnectionWidget.h Qmitk/QmitkToFPointSetWidget.h Qmitk/QmitkToFRecorderWidget.h Qmitk/QmitkToFVisualisationSettingsWidget.h Qmitk/QmitkToFCompositeFilterWidget.h Qmitk/QmitkToFPMDParameterWidget.h Qmitk/QmitkToFMESAParameterWidget.h ) # uncomment the following line if you want to use Qt resources set(QRC_FILES resources/QmitkToFUtilWidget.qrc ) diff --git a/Modules/US/Testing/CMakeLists.txt b/Modules/US/Testing/CMakeLists.txt index 2b3bee20a5..407823e37c 100644 --- a/Modules/US/Testing/CMakeLists.txt +++ b/Modules/US/Testing/CMakeLists.txt @@ -1,10 +1,10 @@ MITK_CREATE_MODULE_TESTS() if(BUILD_TESTING AND MODULE_IS_ENABLED) mitkAddCustomModuleTest(mitkUSImageVideoSourceTest mitkUSImageVideoSourceTest - ${MITK_DATA_DIR}/CommonTestData/bunny_640x480.avi -) + ${MITK_DATA_DIR}/CommonTestData/bunny_320x240.avi +) mitkAddCustomModuleTest(mitkUSPipelineTest mitkUSPipelineTest - ${MITK_DATA_DIR}/CommonTestData/bunny_640x480.avi + ${MITK_DATA_DIR}/CommonTestData/bunny_320x240.avi ) endif() \ No newline at end of file diff --git a/Modules/US/Testing/mitkUSImageVideoSourceTest.cpp b/Modules/US/Testing/mitkUSImageVideoSourceTest.cpp index 80ba8602a5..b5a97498b8 100644 --- a/Modules/US/Testing/mitkUSImageVideoSourceTest.cpp +++ b/Modules/US/Testing/mitkUSImageVideoSourceTest.cpp @@ -1,76 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSImageVideoSource.h" #include "mitkTestingMacros.h" class mitkUSImageVideoSourceTestClass { public: static void TestInstantiation() { // let's create an object of our class mitk::USImageVideoSource::Pointer usSource = mitk::USImageVideoSource::New(); MITK_TEST_CONDITION_REQUIRED(usSource.IsNotNull(), "USImageVideoSource should not be null after instantiation"); } static void TestOpenVideoFile(std::string videoFilePath) { mitk::USImageVideoSource::Pointer usSource = mitk::USImageVideoSource::New(); usSource->SetVideoFileInput(videoFilePath); MITK_TEST_CONDITION_REQUIRED(usSource->GetIsVideoReady(), "USImageVideoSource should have isVideoReady flag set after opening a Video File"); mitk::USImage::Pointer frame; frame = usSource->GetNextImage(); MITK_TEST_CONDITION_REQUIRED(frame.IsNotNull(), "First frame should not be null."); frame = usSource->GetNextImage(); MITK_TEST_CONDITION_REQUIRED(frame.IsNotNull(), "Second frame should not be null."); frame = usSource->GetNextImage(); MITK_TEST_CONDITION_REQUIRED(frame.IsNotNull(), "Third frame should not be null."); frame = usSource->GetNextImage(); MITK_TEST_CONDITION_REQUIRED(frame.IsNotNull(), "Fourth frame should not be null."); frame = usSource->GetNextImage(); MITK_TEST_CONDITION_REQUIRED(frame.IsNotNull(), "Fifth frame should not be null."); } /** This Test will fail if no device is attached. Since it basically covers the same non-OpenCV Functionality as TestOpenVideoFile, it is ommited static void TestOpenDevice() { mitk::USImageVideoSource::Pointer usSource = mitk::USImageVideoSource::New(); usSource->SetCameraInput(-1); MITK_TEST_CONDITION_REQUIRED(usSource->GetIsVideoReady(), "USImageVideoSource should have isVideoReady flag set after opening a Camera device"); } */ }; /** * This function is testing methods of the class USImageVideoSource. */ int mitkUSImageVideoSourceTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkUSImageVideoSourceTest"); mitkUSImageVideoSourceTestClass::TestInstantiation(); - // Removed Until Fix for Linux / Mac is available - //mitkUSImageVideoSourceTestClass::TestOpenVideoFile(argv[1]); + + #ifdef WIN32 // Video file compression is currently only supported under windows. + mitkUSImageVideoSourceTestClass::TestOpenVideoFile(argv[1]); + #endif + + // This test is commented out since no videodevcie ist steadily connected to the dart clients. + // Functionality should sufficiently be tested through TestOpenVideoFile anyway //mitkUSImageVideoSourceTestClass::TestOpenDevice(); MITK_TEST_END(); } \ No newline at end of file diff --git a/Modules/US/Testing/mitkUSPipelineTest.cpp b/Modules/US/Testing/mitkUSPipelineTest.cpp index 8288841a34..a0a3e4239e 100644 --- a/Modules/US/Testing/mitkUSPipelineTest.cpp +++ b/Modules/US/Testing/mitkUSPipelineTest.cpp @@ -1,102 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSVideoDevice.h" #include "mitkTestingMacros.h" #include "mitkUSImageToUSImageFilter.h" #include "mitkPadImageFilter.h" // START TESTFILER // This is an specialization of the USImageToUSImageFIlter class TestUSFilter : public mitk::USImageToUSImageFilter { protected: TestUSFilter() : mitk::USImageToUSImageFilter(){}; virtual ~TestUSFilter(){}; public: mitkClassMacro(TestUSFilter, mitk::USImageToUSImageFilter); itkNewMacro(Self); virtual void GenerateOutputInformation() { mitk::Image::Pointer inputImage = (mitk::Image*) this->GetInput(0); mitk::Image::Pointer output = (mitk::Image*) this->GetOutput(0); if(inputImage.IsNull()) return; }; void GenerateData() { MITK_INFO << "GenerateData called in Testfilter!"; //mitk::Image::Pointer ni = const_cast(this->GetInput(0)); mitk::USImage::Pointer ni = this->GetInput(0); mitk::USImage::Pointer result = mitk::USImage::New(); result->Initialize(ni); result->SetImportVolume(ni->GetData()); mitk::USImageMetadata::Pointer meta = ni->GetMetadata(); meta->SetDeviceComment("Test"); result->SetMetadata(meta); SetNthOutput(0, result); MITK_INFO << "GenerateData completed in Testfilter!"; }; }; // END TESTFILTER class mitkUSPipelineTestClass { public: static void TestPipelineUS(std::string videoFilePath) { // Set up a pipeline mitk::USVideoDevice::Pointer videoDevice = mitk::USVideoDevice::New("C:\\Users\\maerz\\Videos\\Debut\\us.avi", "Manufacturer", "Model"); TestUSFilter::Pointer filter = TestUSFilter::New(); videoDevice->Update(); filter->SetInput(videoDevice->GetOutput()); filter->Update(); MITK_TEST_CONDITION_REQUIRED(videoDevice.IsNotNull(), "videoDevice should not be null after instantiation"); //mitk::USImage::Pointer result = dynamic_cast (filter->GetOutput(0)); mitk::USImage::Pointer result = filter->GetOutput(0); MITK_TEST_CONDITION_REQUIRED(result.IsNotNull(), "resulting images should not be null"); std::string model = result->GetMetadata()->GetDeviceModel(); MITK_TEST_CONDITION_REQUIRED(model.compare("Model") == 0 , "Resulting images should have their metadata set correctly"); } }; /** * This function is setting up a pipeline and checks the output for validity. */ int mitkUSPipelineTest(int argc , char* argv[]) { MITK_TEST_BEGIN("mitkUSPipelineTest"); - // Removed Until Fix for Linux / Mac is available - // mitkUSPipelineTestClass::TestPipelineUS(argv[1]); - - + + #ifdef WIN32 // Video file compression is currently only supported under windows. + mitkUSPipelineTestClass::TestPipelineUS(argv[1]); + #endif MITK_TEST_END(); } \ No newline at end of file diff --git a/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.cpp index 65f69cff14..8d4539ab61 100644 --- a/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.cpp @@ -1,19 +1,34 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { Q_UNUSED(context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_core_jobs, mitk::PluginActivator) diff --git a/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.h index aabb457032..dc7ad4f70c 100644 --- a/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.core.jobs/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.cpp b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.cpp index e82f568508..30cf9351f8 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.cpp +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.cpp @@ -1,20 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkBasicImageProcessingActivator.h" #include "QmitkBasicImageProcessingView.h" #include namespace mitk { void BasicImageProcessingActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkBasicImageProcessing, context) } void BasicImageProcessingActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_basicimageprocessing, mitk::BasicImageProcessingActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.h b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.h index ab68ff7556..a7112f3acd 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.h +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/mitkBasicImageProcessingActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKBASICIMAGEPROCESSINGACTIVATOR_H #define MITKBASICIMAGEPROCESSINGACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL BasicImageProcessingActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // basicImageProcessingActivator } #endif // MITKBASICIMAGEPROCESSINGACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.cpp index ad5bd9850f..809215af3f 100644 --- a/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.cpp @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "../QmitkQtCommonTestSuite.h" #include "../api/QmitkMockFunctionality.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkQtCommonTestSuite, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkMockFunctionality, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_common.tests, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.h index a34be34be4..259bc9ffd6 100644 --- a/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.common/testing/src/internal/mitkPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include namespace mitk { class PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.cpp index 1421feec88..e774ec0ae8 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.cpp @@ -1,27 +1,42 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkPropertyListView.h" #include "../QmitkDataManagerView.h" #include "../QmitkDataManagerPreferencePage.h" #include "../QmitkDataManagerHotkeysPrefPage.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDataManagerView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPropertyListView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDataManagerPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDataManagerHotkeysPrefPage, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_datamanager, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.h index 0436a647ad..ca951ddd3f 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.datamanager/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/mitkIContextMenuAction.h b/Plugins/org.mitk.gui.qt.datamanager/src/mitkIContextMenuAction.h index d0b7ae1b70..b99d843b2b 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/mitkIContextMenuAction.h +++ b/Plugins/org.mitk.gui.qt.datamanager/src/mitkIContextMenuAction.h @@ -1,41 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef mitkIContextMenuAction_H_ #define mitkIContextMenuAction_H_ #include #include #include #include #include "mitkDataStorage.h" class QmitkStdMultiWidget; namespace mitk { /** * A context menu action, which is linked to the context menu
* through an extension point. For an example check the
* plugin.xml and the connected classes of
* the the segmentation bundle and also the QmitkDataManagerView.cpp
* in this bundle. */ struct IContextMenuAction { berryInterfaceMacro(IContextMenuAction, mitk) /** * @brief Executes the action, that linked to the context menu entry. */ virtual void Run( const QList& selectedNodes ) = 0; // Setters virtual void SetDataStorage(mitk::DataStorage* dataStorage) = 0; virtual void SetSmoothed(bool smoothed) = 0; virtual void SetDecimated(bool decimated) = 0; virtual void SetFunctionality(berry::QtViewPart* functionality) = 0; }; } Q_DECLARE_INTERFACE(mitk::IContextMenuAction, "org.mitk.datamanager.IContextMenuAction") #endif // mitkIContextMenuAction_H_ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp index 10123892ec..ab313319e9 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp @@ -1,441 +1,459 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include #include const std::string QmitkPreprocessingView::VIEW_ID = -"org.mitk.views.preprocessing"; + "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; QmitkPreprocessingView::QmitkPreprocessingView() -: QmitkFunctionality(), -m_Controls(NULL), -m_MultiWidget(NULL), -m_DiffusionImage(NULL) + : QmitkFunctionality(), + m_Controls(NULL), + m_MultiWidget(NULL), + m_DiffusionImage(NULL) { } QmitkPreprocessingView::QmitkPreprocessingView(const QmitkPreprocessingView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); } } void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkPreprocessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ButtonBrainMask), SIGNAL(clicked()), this, SLOT(BrainMask()) ); connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); } } void QmitkPreprocessingView::OnSelectionChanged( std::vector nodes ) { bool foundDwiVolume = false; m_DiffusionImage = NULL; m_SelectedDiffusionNodes = mitk::DataStorage::SetOfObjects::New(); // iterate selection for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast*>(node->GetData()) ) { foundDwiVolume = true; m_DiffusionImage = dynamic_cast*>(node->GetData()); m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_SelectedDiffusionNodes->push_back(node); } } m_Controls->m_ButtonBrainMask->setEnabled(foundDwiVolume); m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume); m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume); m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); if (foundDwiVolume) { vnl_matrix_fixed< double, 3, 3 > mf = m_DiffusionImage->GetMeasurementFrame(); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } - m_Controls->m_GradientsLabel->setText(QString::number(m_DiffusionImage->GetNumDirections())); - if (m_DiffusionImage->IsMultiBval()) - m_Controls->m_BvalLabel->setText("Acquisition with multiple b-values!"); - else - m_Controls->m_BvalLabel->setText(QString::number(m_DiffusionImage->GetB_Value())); + typedef mitk::DiffusionImage::BValueMap BValueMap; + typedef mitk::DiffusionImage::BValueMap::iterator BValueMapIterator; + + BValueMap bValMap = m_DiffusionImage->GetB_ValueMap(); + BValueMapIterator it = bValMap.begin(); + m_Controls->m_BvalueTable->clear(); + m_Controls->m_BvalueTable->setRowCount(bValMap.size() ); + QStringList headerList; + headerList << "b-Value" << "Number of gradients"; + m_Controls->m_BvalueTable->setHorizontalHeaderLabels(headerList); + int i = 0 ; + for(;it != bValMap.end(); it++) + { + m_Controls->m_BvalueTable->setItem(i,0,new QTableWidgetItem(QString::number(it->first))); + m_Controls->m_BvalueTable->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size()))); + i++; + } + } else { for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } - m_Controls->m_GradientsLabel->setText("-"); - m_Controls->m_BvalLabel->setText("-"); + m_Controls->m_BvalueTable->clear(); + m_Controls->m_BvalueTable->setRowCount(1); + QStringList headerList; + headerList << "b-Value" << "Number of gradients"; + m_Controls->m_BvalueTable->setHorizontalHeaderLabels(headerList); + m_Controls->m_BvalueTable->setItem(0,0,new QTableWidgetItem("-")); + m_Controls->m_BvalueTable->setItem(0,1,new QTableWidgetItem("-")); m_Controls->m_DiffusionImageLabel->setText("-"); } } void QmitkPreprocessingView::Activated() { QmitkFunctionality::Activated(); } void QmitkPreprocessingView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { if (m_DiffusionImage.IsNull()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); for (int j=0; jSize(); j++) if (gradientContainer->at(j)[0]<0) gradientContainer->at(j) = -gradientContainer->at(j); } void QmitkPreprocessingView::DoApplyMesurementFrame() { if (m_DiffusionImage.IsNull()) return; vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) return; mf[r][c] = item->text().toDouble(); } m_DiffusionImage->SetMeasurementFrame(mf); } void QmitkPreprocessingView::DoShowGradientDirections() { if (m_DiffusionImage.IsNull()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (int j=0; jSize(); j++) { mitk::Point3D p; vnl_vector_fixed< double, 3 > v = gradientContainer->at(j); if (fabs(v[0])>0.001 || fabs(v[1])>0.001 || fabs(v[2])>0.001) { p[0] = v[0]; p[1] = v[1]; p[2] = v[2]; pointset->InsertPoint(j, p); } } mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(pointset); node->SetName("gradient directions"); node->SetProperty("pointsize", mitk::FloatProperty::New(0.05)); node->SetProperty("color", mitk::ColorProperty::New(1,0,0)); GetDefaultDataStorage()->Add(node); } void QmitkPreprocessingView::DoReduceGradientDirections() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage DiffusionImageType; typedef itk::ReduceDirectionGradientsFilter FilterType; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(m_DiffusionImage->GetVectorImage()); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(m_Controls->m_ReduceGradientsBox->value()); filter->Update(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(m_DiffusionImage->GetB_Value()); image->SetDirections(filter->GetGradientDirections()); image->SetOriginalDirections(filter->GetGradientDirections()); image->SetMeasurementFrame(m_DiffusionImage->GetMeasurementFrame()); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); imageNode->SetName("reduced_image"); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; int nrFiles = m_SelectedDiffusionNodes->size(); if (!nrFiles) return; // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = - static_cast( - (*itemiter)->GetData()); + static_cast( + (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { // typedefs typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; // check number of selected objects, return if empty int nrFiles = m_SelectedDiffusionNodes->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes->end() ); std::vector< mitk::DataNode::Pointer > nodes; while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = - static_cast( - (*itemiter)->GetData()); + static_cast( + (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); - mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0_ALL")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::AverageGradients() { int nrFiles = m_SelectedDiffusionNodes->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = - static_cast*>( - (*itemiter)->GetData()); + static_cast*>( + (*itemiter)->GetData()); vols->AverageRedundantGradients(m_Controls->m_Blur->value()); ++itemiter; } } void QmitkPreprocessingView::BrainMask() { int nrFiles = m_SelectedDiffusionNodes->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes->end() ); while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = - static_cast*>( - (*itemiter)->GetData()); + static_cast*>( + (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); typedef itk::CastImageFilter, itk::Image > CastFilterType; CastFilterType::Pointer castfilter = CastFilterType::New(); castfilter->SetInput(filter->GetOutput()); typedef itk::BrainMaskExtractionImageFilter MaskFilterType; MaskFilterType::Pointer maskfilter = MaskFilterType::New(); maskfilter->SetInput(castfilter->GetOutput()); maskfilter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( maskfilter->GetOutput() ); mitkImage->SetVolume( maskfilter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_Mask")); GetDefaultDataStorage()->Add(node); ++itemiter; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui index c67d78669e..7fe02fe94a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui @@ -1,529 +1,555 @@ QmitkPreprocessingViewControls 0 0 389 - 913 + 984 0 0 - true + false QmitkPreprocessingViewControls + + true + Data Diffusion Image: - + + + 0 + 0 + + Info - - - QFormLayout::AllNonFixedFieldsGrow - + - - - Number of Gradients: - - - - - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - b-Value: + + + + 0 + 0 + - - - - - - - + + Qt::ScrollBarAsNeeded - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + Qt::ScrollBarAlwaysOff + + true + + + 100 + + + true + + + false + + + true + + + + b-Value + + + + + Number of gradients + + - + false Generate pointset displaying the gradient vectors. Show gradients + + + + Qt::Horizontal + + + + 40 + 20 + + + + Reduce size 0 70 Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them anyway by taking into account all directions within a certain radius. true QFrame::NoFrame QFrame::Raised 0 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. 6 2.000000000000000 0.000100000000000 0.001000000000000 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Merge radius false Average redundant gradients false Mirror all gradients around one axis. Mirror gradients to half sphere Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 0 0 New number of gradients: 1 30 false Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere. Reduce number of gradients Non diffusion weighted image 0 30 Average and extract all images that were acquired without diffusion weighting. true false Extract B0 Create a 3D+t data set containing all b0 images as timesteps Extract all B0 without averaging Brain mask false Estimate binary brain mask 0 0 Measurment frame Qt::Horizontal 40 20 false 0 0 10 10 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true false true true New Row New Row New Row New Column New Column New Column false Apply new mesurement frame Qt::Vertical 20 40 diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp index 9c33c46767..96d51602d2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp @@ -1,1419 +1,1419 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTensorReconstructionView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include #include #include #include #include // itk includes #include "itkTimeProbe.h" //#include "itkTensor.h" // mitk includes #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h" #include "itkDiffusionTensor3DReconstructionImageFilter.h" #include "itkTensorImageToDiffusionImageFilter.h" #include "itkPointShell.h" #include "itkVector.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkTensorReconstructionWithEigenvalueCorrectionFilter.h" //#include "itkFreeWaterEliminationFilter.h" #include "mitkProperties.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkDiffusionImageMapper.h" #include "mitkLookupTableProperty.h" #include "mitkLookupTable.h" #include "mitkImageStatisticsHolder.h" #include #include const std::string QmitkTensorReconstructionView::VIEW_ID = "org.mitk.views.tensorreconstruction"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; using namespace berry; struct TrSelListener : ISelectionListener { berryObjectMacro(TrSelListener); TrSelListener(QmitkTensorReconstructionView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { /* // if(!m_View->IsVisible()) // return; // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundDwiVolume = false; bool foundTensorVolume = false; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) { foundDwiVolume = true; } // only look at interesting types if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) { foundTensorVolume = true; } } } m_View->m_Controls->m_ItkReconstruction->setEnabled(foundDwiVolume); m_View->m_Controls->m_TeemReconstruction->setEnabled(foundDwiVolume); m_View->m_Controls->m_ReconstructionWithCorrection->setEnabled(foundDwiVolume); m_View->m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_ResidualButton->setEnabled(foundDwiVolume && foundTensorVolume); m_View->m_Controls->m_PercentagesOfOutliers->setEnabled(foundDwiVolume && foundTensorVolume); m_View->m_Controls->m_PerSliceView->setEnabled(foundDwiVolume && foundTensorVolume); } */ } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkTensorReconstructionView* m_View; }; QmitkTensorReconstructionView::QmitkTensorReconstructionView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL) { m_DiffusionImages = mitk::DataStorage::SetOfObjects::New(); m_TensorImages = mitk::DataStorage::SetOfObjects::New(); } QmitkTensorReconstructionView::QmitkTensorReconstructionView(const QmitkTensorReconstructionView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkTensorReconstructionView::~QmitkTensorReconstructionView() { } void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTensorReconstructionViewControls; m_Controls->setupUi(parent); this->CreateConnections(); QStringList items; items << "LLS (Linear Least Squares)" << "MLE (Maximum Likelihood)" << "NLS (Nonlinear Least Squares)" << "WLS (Weighted Least Squares)"; m_Controls->m_TensorEstimationTeemEstimationMethodCombo->addItems(items); m_Controls->m_TensorEstimationTeemEstimationMethodCombo->setCurrentIndex(0); m_Controls->m_TensorEstimationManualThreashold->setChecked(false); m_Controls->m_TensorEstimationTeemSigmaEdit->setText("NaN"); m_Controls->m_TensorEstimationTeemNumItsSpin->setValue(1); m_Controls->m_TensorEstimationTeemFuzzyEdit->setText("0.0"); m_Controls->m_TensorEstimationTeemMinValEdit->setText("1.0"); m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(true); m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(true); m_Controls->m_TensorsToDWIBValueEdit->setText("1000"); Advanced1CheckboxClicked(); Advanced2CheckboxClicked(); Advanced3CheckboxClicked(); TeemCheckboxClicked(); #ifndef DIFFUSION_IMAGING_EXTENDED m_Controls->m_TeemToggle->setVisible(false); #endif // define data type for combobox //m_Controls->m_ImageSelector->SetDataStorage( this->GetDefaultDataStorage() ); //m_Controls->m_ImageSelector->SetPredicate( mitk::NodePredicateDataType::New("DiffusionImage") ); } } void QmitkTensorReconstructionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTensorReconstructionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTensorReconstructionView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_TeemToggle), SIGNAL(clicked()), this, SLOT(TeemCheckboxClicked()) ); connect( (QObject*)(m_Controls->m_ItkReconstruction), SIGNAL(clicked()), this, SLOT(ItkReconstruction()) ); connect( (QObject*)(m_Controls->m_TeemReconstruction), SIGNAL(clicked()), this, SLOT(TeemReconstruction()) ); connect( (QObject*)(m_Controls->m_ReconstructionWithCorrection), SIGNAL(clicked()), this, SLOT(ReconstructionWithCorrection()) ); connect( (QObject*)(m_Controls->m_TensorEstimationTeemEstimationMethodCombo), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) ); connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_Advanced2), SIGNAL(clicked()), this, SLOT(Advanced2CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_Advanced3), SIGNAL(clicked()), this, SLOT(Advanced3CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_TensorEstimationManualThreashold), SIGNAL(clicked()), this, SLOT(ManualThresholdClicked()) ); connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) ); connect( (QObject*)(m_Controls->m_TensorsToQbiButton), SIGNAL(clicked()), this, SLOT(TensorsToQbi()) ); connect( (QObject*)(m_Controls->m_ResidualButton), SIGNAL(clicked()), this, SLOT(ResidualCalculation()) ); connect( (QObject*)(m_Controls->m_PerSliceView), SIGNAL(pointSelected(int, int)), this, SLOT(ResidualClicked(int, int)) ); } } void QmitkTensorReconstructionView::ResidualClicked(int slice, int volume) { // Use image coord to reset crosshair // Find currently selected diffusion image // Update Label // to do: This position should be modified in order to skip B0 volumes that are not taken into account // when calculating residuals // Find the diffusion image mitk::DiffusionImage* diffImage; mitk::DataNode::Pointer correctNode; mitk::Geometry3D* geometry; if (m_DiffusionImage.IsNotNull()) { diffImage = static_cast*>(m_DiffusionImage->GetData()); geometry = diffImage->GetGeometry(); // Remember the node whose display index must be updated correctNode = mitk::DataNode::New(); correctNode = m_DiffusionImage; } if(diffImage != NULL) { typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; GradientDirectionContainerType::Pointer dirs = diffImage->GetDirections(); for(int i=0; iSize() && i<=volume; i++) { GradientDirectionType grad = dirs->ElementAt(i); // check if image is b0 weighted if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001) { volume++; } } QString pos = "Volume: "; pos.append(QString::number(volume)); pos.append(", Slice: "); pos.append(QString::number(slice)); m_Controls->m_PositionLabel->setText(pos); if(correctNode) { int oldDisplayVal; correctNode->GetIntProperty("DisplayChannel", oldDisplayVal); std::string oldVal = QString::number(oldDisplayVal).toStdString(); std::string newVal = QString::number(volume).toStdString(); correctNode->SetIntProperty("DisplayChannel",volume); correctNode->SetSelected(true); this->FirePropertyChanged("DisplayChannel", oldVal, newVal); correctNode->UpdateOutputInformation(); mitk::Point3D p3 = m_MultiWidget->GetCrossPosition(); itk::Index<3> ix; geometry->WorldToIndex(p3, ix); // ix[2] = slice; mitk::Vector3D vec; vec[0] = ix[0]; vec[1] = ix[1]; vec[2] = slice; mitk::Vector3D v3New; geometry->IndexToWorld(vec, v3New); mitk::Point3D origin = geometry->GetOrigin(); mitk::Point3D p3New; p3New[0] = v3New[0] + origin[0]; p3New[1] = v3New[1] + origin[1]; p3New[2] = v3New[2] + origin[2]; m_MultiWidget->MoveCrossToPosition(p3New); m_MultiWidget->RequestUpdate(); } } } void QmitkTensorReconstructionView::TeemCheckboxClicked() { m_Controls->groupBox_3->setVisible(m_Controls-> m_TeemToggle->isChecked()); } void QmitkTensorReconstructionView::Advanced1CheckboxClicked() { bool check = m_Controls-> m_Advanced1->isChecked(); m_Controls->frame->setVisible(check); } void QmitkTensorReconstructionView::Advanced2CheckboxClicked() { bool check = m_Controls-> m_Advanced2->isChecked(); m_Controls->frame_2->setVisible(check); } void QmitkTensorReconstructionView::Advanced3CheckboxClicked() { bool check = m_Controls-> m_Advanced3->isChecked(); m_Controls->frame_6->setVisible(check); } void QmitkTensorReconstructionView::ManualThresholdClicked() { m_Controls->m_TensorReconstructionThreasholdEdit_2->setEnabled( m_Controls->m_TensorEstimationManualThreashold->isChecked()); } void QmitkTensorReconstructionView::Activated() { QmitkFunctionality::Activated(); } void QmitkTensorReconstructionView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTensorReconstructionView::MethodChoosen(int method) { m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(method==3); m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(method==3); } void QmitkTensorReconstructionView::ResidualCalculation() { // Extract dwi and dti from current selection // In case of multiple selections, take the first one, since taking all combinations is not meaningful mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::DiffusionImage::Pointer diffImage = mitk::DiffusionImage::New(); TensorImageType::Pointer tensorImage; std::string nodename; if(m_DiffusionImage.IsNotNull()) { diffImage = static_cast*>(m_DiffusionImage->GetData()); } else return; if(m_TensorImage.IsNotNull()) { mitk::TensorImage* mitkVol; mitkVol = static_cast(m_TensorImage->GetData()); mitk::CastToItkImage(mitkVol, tensorImage); m_TensorImage->GetStringProperty("name", nodename); } else return; typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; FilterType::GradientListType gradientList; mitk::DiffusionImage::GradientDirectionContainerType* gradients = diffImage->GetDirections(); // Copy gradients vectors from gradients to gradientList for(int i=0; iSize(); i++) { mitk::DiffusionImage::GradientDirectionType vec = gradients->at(i); itk::Vector grad; grad[0] = vec[0]; grad[1] = vec[1]; grad[2] = vec[2]; gradientList.push_back(grad); } // Find the min and the max values from a baseline image mitk::ImageStatisticsHolder *stats = diffImage->GetStatistics(); //Initialize filter that calculates the modeled diffusion weighted signals FilterType::Pointer filter = FilterType::New(); filter->SetInput( tensorImage ); filter->SetBValue(diffImage->GetB_Value()); filter->SetGradientList(gradientList); filter->SetMin(stats->GetScalarValueMin()); filter->SetMax(500); filter->Update(); // TENSORS TO DATATREE mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(diffImage->GetB_Value()); image->SetDirections(gradientList); image->SetOriginalDirections(gradientList); image->InitializeFromVectorImage(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); mitk::DiffusionImageMapper::SetDefaultProperties(node); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dwi"); node->SetName(newname.toAscii()); GetDefaultDataStorage()->Add(node); - std::vector b0Indices = image->GetB0Indices(); + std::vector b0Indices = image->GetB0Indices(); typedef itk::ResidualImageFilter ResidualImageFilterType; ResidualImageFilterType::Pointer residualFilter = ResidualImageFilterType::New(); residualFilter->SetInput(diffImage->GetVectorImage()); residualFilter->SetSecondDiffusionImage(image->GetVectorImage()); residualFilter->SetGradients(gradients); residualFilter->SetB0Index(b0Indices[0]); residualFilter->SetB0Threshold(30); residualFilter->Update(); itk::Image::Pointer residualImage = itk::Image::New(); residualImage = residualFilter->GetOutput(); mitk::Image::Pointer mitkResImg = mitk::Image::New(); mitk::CastToMitkImage(residualImage, mitkResImg); stats = mitkResImg->GetStatistics(); float min = stats->GetScalarValueMin(); float max = stats->GetScalarValueMax(); mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(min, max); // If you don't want to use the whole color range, you can use // SetValueRange, SetHueRange, and SetSaturationRange lookupTable->Build(); int size = lookupTable->GetTable()->GetSize(); vtkSmartPointer reversedlookupTable = vtkSmartPointer::New(); reversedlookupTable->SetTableRange(min+1, max); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookupTable->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } lut->SetVtkLookupTable(lookupTable); lutProp->SetLookupTable(lut); // Create lookuptable mitk::DataNode::Pointer resNode=mitk::DataNode::New(); resNode->SetData( mitkResImg ); resNode->SetName("Residual Image"); resNode->SetProperty("LookupTable", lutProp); bool b; resNode->GetBoolProperty("use color", b); resNode->SetBoolProperty("use color", false); GetDefaultDataStorage()->Add(resNode); m_MultiWidget->RequestUpdate(); // Draw Graph std::vector means = residualFilter->GetMeans(); std::vector q1s = residualFilter->GetQ1(); std::vector q3s = residualFilter->GetQ3(); std::vector percentagesOfOUtliers = residualFilter->GetPercentagesOfOutliers(); m_Controls->m_ResidualAnalysis->SetMeans(means); m_Controls->m_ResidualAnalysis->SetQ1(q1s); m_Controls->m_ResidualAnalysis->SetQ3(q3s); m_Controls->m_ResidualAnalysis->SetPercentagesOfOutliers(percentagesOfOUtliers); if(m_Controls->m_PercentagesOfOutliers->isChecked()) { m_Controls->m_ResidualAnalysis->DrawPercentagesOfOutliers(); } else { m_Controls->m_ResidualAnalysis->DrawMeans(); } // Draw Graph for volumes per slice in the QGraphicsView std::vector< std::vector > outliersPerSlice = residualFilter->GetOutliersPerSlice(); int xSize = outliersPerSlice.size(); if(xSize == 0) { return; } int ySize = outliersPerSlice[0].size(); // Find maximum in outliersPerSlice double maxOutlier= 0.0; for(int i=0; imaxOutlier) { maxOutlier = outliersPerSlice[i][j]; } } } // Create some QImage QImage qImage(xSize, ySize, QImage::Format_RGB32); QImage legend(1, 256, QImage::Format_RGB32); QRgb value; vtkSmartPointer lookup = vtkSmartPointer::New(); lookup->SetTableRange(0.0, maxOutlier); lookup->Build(); reversedlookupTable->SetTableRange(0, maxOutlier); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookup->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } // Fill qImage for(int i=0; iMapValue(out); int r, g, b; r = _rgba[0]; g = _rgba[1]; b = _rgba[2]; value = qRgb(r, g, b); qImage.setPixel(i,j,value); } } for(int i=0; i<256; i++) { double* rgba = lookup->GetTableValue(i); int r, g, b; r = rgba[0]*255; g = rgba[1]*255; b = rgba[2]*255; value = qRgb(r, g, b); legend.setPixel(0,255-i,value); } QString upper = QString::number(maxOutlier, 'g', 3); upper.append(" %"); QString lower = QString::number(0.0); lower.append(" %"); m_Controls->m_UpperLabel->setText(upper); m_Controls->m_LowerLabel->setText(lower); QGraphicsScene* scene = new QGraphicsScene; QGraphicsScene* scene2 = new QGraphicsScene; QPixmap pixmap(QPixmap::fromImage(qImage)); QGraphicsPixmapItem *item = new QGraphicsPixmapItem( pixmap, 0, scene); item->scale(10.0, 3.0); QPixmap pixmap2(QPixmap::fromImage(legend)); QGraphicsPixmapItem *item2 = new QGraphicsPixmapItem( pixmap2, 0, scene2); item2->scale(20.0, 1.0); m_Controls->m_PerSliceView->SetResidualPixmapItem(item); m_Controls->m_PerSliceView->setScene(scene); m_Controls->m_LegendView->setScene(scene2); m_Controls->m_PerSliceView->show(); m_Controls->m_PerSliceView->repaint(); m_Controls->m_LegendView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->show(); m_Controls->m_LegendView->repaint(); } void QmitkTensorReconstructionView::ItkReconstruction() { Reconstruct(0); } void QmitkTensorReconstructionView::TeemReconstruction() { Reconstruct(1); } void QmitkTensorReconstructionView::ReconstructionWithCorrection() { Reconstruct(2); } void QmitkTensorReconstructionView::Reconstruct(int method) { if(method == 0) ItkTensorReconstruction(m_DiffusionImages); if(method == 1) TeemTensorReconstruction(m_DiffusionImages); if(method == 2) { TensorReconstructionWithCorr(m_DiffusionImages); } } void QmitkTensorReconstructionView::TensorReconstructionWithCorr (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { typedef mitk::DiffusionImage DiffusionImageType; DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // TENSOR RECONSTRUCTION clock.Start(); MBI_INFO << "Tensor reconstruction with correction for negative eigenvalues"; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Tensor reconstruction for %s", nodename.c_str()).toAscii()); typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< DiffusionPixelType, TTensorPixelType > ReconstructionFilter; float b0Threshold = m_Controls->m_ReconstructionThreshold->text().toFloat(); ReconstructionFilter::Pointer reconFilter = ReconstructionFilter::New(); reconFilter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() ); reconFilter->SetBValue(vols->GetB_Value()); reconFilter->SetB0Threshold(b0Threshold); reconFilter->Update(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer outputTensorImg = reconFilter->GetOutput(); typedef itk::ImageRegionIterator TensorImageIteratorType; TensorImageIteratorType tensorIt(outputTensorImg, outputTensorImg->GetRequestedRegion()); tensorIt.GoToBegin(); int negatives = 0; while(!tensorIt.IsAtEnd()) { typedef itk::DiffusionTensor3D TensorType; TensorType tensor = tensorIt.Get(); TensorType::EigenValuesArrayType ev; tensor.ComputeEigenValues(ev); for(unsigned int i=0; iInitializeByItk( outputTensorImg.GetPointer() ); image->SetVolume( outputTensorImg->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dti"); SetDefaultNodeProperties(node, newname.toStdString()); nodes.push_back(node); // Corrected diffusion image typedef itk::VectorImage ImageType; ImageType::Pointer correctedVols = reconFilter->GetVectorImage(); DiffusionImageType::Pointer correctedDiffusion = DiffusionImageType::New(); correctedDiffusion->SetVectorImage(correctedVols); correctedDiffusion->SetDirections(vols->GetDirections()); correctedDiffusion->SetB_Value(vols->GetB_Value()); correctedDiffusion->SetOriginalDirections(vols->GetDirections()); correctedDiffusion->InitializeFromVectorImage(); mitk::DataNode::Pointer diffNode=mitk::DataNode::New(); diffNode->SetData( correctedDiffusion ); QString diffname; diffname = diffname.append(nodename.c_str()); diffname = diffname.append("corrDiff"); SetDefaultNodeProperties(diffNode, diffname.toStdString()); nodes.push_back(diffNode); // B0 mask as used in tensorreconstructionwithcorrectionfilter typedef itk::Image MaskImageType; MaskImageType::Pointer mask = reconFilter->GetMask(); mitk::Image::Pointer mitkMask; mitk::CastToMitkImage(mask, mitkMask); mitk::DataNode::Pointer maskNode=mitk::DataNode::New(); maskNode->SetData( mitkMask ); QString maskname; maskname = maskname.append(nodename.c_str()); maskname = maskname.append("_mask"); SetDefaultNodeProperties(maskNode, maskname.toStdString()); nodes.push_back(maskNode); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkTensorReconstructionView::ItkTensorReconstruction (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // TENSOR RECONSTRUCTION clock.Start(); MBI_INFO << "Tensor reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Tensor reconstruction for %s", nodename.c_str()).toAscii()); typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); tensorReconstructionFilter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() ); tensorReconstructionFilter->SetBValue(vols->GetB_Value()); tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreasholdEdit->text().toFloat() ); tensorReconstructionFilter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; // TENSORS TO DATATREE mitk::TensorImage::Pointer image = mitk::TensorImage::New(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer tensorImage; tensorImage = tensorReconstructionFilter->GetOutput(); // Check the tensor for negative eigenvalues if(m_Controls->m_CheckNegativeEigenvalues->isChecked()) { typedef itk::ImageRegionIterator TensorImageIteratorType; TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion()); tensorIt.GoToBegin(); while(!tensorIt.IsAtEnd()) { typedef itk::DiffusionTensor3D TensorType; //typedef itk::Tensor TensorType2; TensorType tensor = tensorIt.Get(); // TensorType2 tensor2; /* for(int i=0; i SymEigenSystemType; SymEigenSystemType eig (tensor2.GetVnlMatrix()); for(unsigned int i=0; iInitializeByItk( tensorImage.GetPointer() ); image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dti"); SetDefaultNodeProperties(node, newname.toStdString()); nodes.push_back(node); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkTensorReconstructionView::TeemTensorReconstruction (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // TENSOR RECONSTRUCTION clock.Start(); MBI_INFO << "Teem Tensor reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Teem Tensor reconstruction for %s", nodename.c_str()).toAscii()); typedef mitk::TeemDiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); tensorReconstructionFilter->SetInput( vols ); if(!m_Controls->m_TensorEstimationTeemSigmaEdit->text().contains(QString("NaN"))) tensorReconstructionFilter->SetSigma( m_Controls->m_TensorEstimationTeemSigmaEdit->text().toFloat() ); switch(m_Controls->m_TensorEstimationTeemEstimationMethodCombo->currentIndex()) { // items << "LLS (Linear Least Squares)" //<< "MLE (Maximum Likelihood)" //<< "NLS (Nonlinear Least Squares)" //<< "WLS (Weighted Least Squares)"; case 0: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS); break; case 1: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsMLE); break; case 2: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsNLS); break; case 3: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsWLS); break; default: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS); } tensorReconstructionFilter->SetNumIterations( m_Controls->m_TensorEstimationTeemNumItsSpin->value() ); if(m_Controls->m_TensorEstimationManualThreashold->isChecked()) tensorReconstructionFilter->SetConfidenceThreshold( m_Controls->m_TensorReconstructionThreasholdEdit_2->text().toDouble() ); tensorReconstructionFilter->SetConfidenceFuzzyness( m_Controls->m_TensorEstimationTeemFuzzyEdit->text().toFloat() ); tensorReconstructionFilter->SetMinPlausibleValue( m_Controls->m_TensorEstimationTeemMinValEdit->text().toDouble() ); tensorReconstructionFilter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s." ; // TENSORS TO DATATREE mitk::DataNode::Pointer node2=mitk::DataNode::New(); node2->SetData( tensorReconstructionFilter->GetOutputItk() ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dtix"); SetDefaultNodeProperties(node2, newname.toStdString()); nodes.push_back(node2); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkTensorReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); //node->SetProperty( "opacity", mitk::FloatProperty::New(1.0f) ); node->SetProperty( "name", mitk::StringProperty::New(name) ); } //node->SetProperty( "volumerendering", mitk::BoolProperty::New( false ) ); //node->SetProperty( "use color", mitk::BoolProperty::New( true ) ); //node->SetProperty( "texture interpolation", mitk::BoolProperty::New( true ) ); //node->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); //node->SetProperty( "layer", mitk::IntProperty::New(0)); //node->SetProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); //node->SetOpacity(1.0f); //node->SetColor(1.0,1.0,1.0); //node->SetVisibility(true); //node->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) ); //mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); //mitk::LevelWindow levelwindow; //// levelwindow.SetAuto( image ); //levWinProp->SetLevelWindow( levelwindow ); //node->GetPropertyList()->SetProperty( "levelwindow", levWinProp ); //// add a default rainbow lookup table for color mapping //if(!node->GetProperty("LookupTable")) //{ // mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); // vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); // vtkLut->SetHueRange(0.6667, 0.0); // vtkLut->SetTableRange(0.0, 20.0); // vtkLut->Build(); // mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); // mitkLutProp->SetLookupTable(mitkLut); // node->SetProperty( "LookupTable", mitkLutProp ); //} //if(!node->GetProperty("binary")) // node->SetProperty( "binary", mitk::BoolProperty::New( false ) ); //// add a default transfer function //mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); //node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); //// set foldername as string property //mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name ); //node->SetProperty( "name", nameProp ); void QmitkTensorReconstructionView::TensorsToDWI() { DoTensorsToDWI(m_TensorImages); } void QmitkTensorReconstructionView::TensorsToQbi() { for (int i=0; isize(); i++) { mitk::DataNode::Pointer tensorImageNode = m_TensorImages->at(i); MITK_INFO << "starting Q-Ball estimation"; typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(dynamic_cast(tensorImageNode->GetData()), itkvol); typedef itk::TensorImageToQBallImageFilter< TTensorPixelType, TTensorPixelType > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->Update(); typedef itk::Vector OutputPixelType; typedef itk::Image OutputImageType; mitk::QBallImage::Pointer image = mitk::QBallImage::New(); OutputImageType::Pointer outimg = filter->GetOutput(); image->InitializeByItk( outimg.GetPointer() ); image->SetVolume( outimg->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(tensorImageNode->GetName().c_str()); newname = newname.append("_qbi"); node->SetName(newname.toAscii()); GetDefaultDataStorage()->Add(node); } } void QmitkTensorReconstructionView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) return; m_DiffusionImages = mitk::DataStorage::SetOfObjects::New(); m_TensorImages = mitk::DataStorage::SetOfObjects::New(); bool foundDwiVolume = false; bool foundTensorVolume = false; m_Controls->m_DiffusionImageLabel->setText("-"); m_Controls->m_TensorImageLabel->setText("-"); m_DiffusionImage = NULL; m_TensorImage = NULL; // iterate selection for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if (node.IsNull()) continue; // only look at interesting types if(dynamic_cast*>(node->GetData())) { foundDwiVolume = true; m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_DiffusionImages->push_back(node); m_DiffusionImage = node; } else if(dynamic_cast(node->GetData())) { foundTensorVolume = true; m_Controls->m_TensorImageLabel->setText(node->GetName().c_str()); m_TensorImages->push_back(node); m_TensorImage = node; } } m_Controls->m_ItkReconstruction->setEnabled(foundDwiVolume); m_Controls->m_TeemReconstruction->setEnabled(foundDwiVolume); m_Controls->m_ReconstructionWithCorrection->setEnabled(foundDwiVolume); m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume); m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume); m_Controls->m_ResidualButton->setEnabled(foundDwiVolume && foundTensorVolume); m_Controls->m_PercentagesOfOutliers->setEnabled(foundDwiVolume && foundTensorVolume); m_Controls->m_PerSliceView->setEnabled(foundDwiVolume && foundTensorVolume); } template std::vector > QmitkTensorReconstructionView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); for(int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } // Add 0 vector for B0 itk::Vector v; v.Fill(0.0); retval.push_back(v); return retval; } void QmitkTensorReconstructionView::DoTensorsToDWI (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { std::string nodename; (*itemiter)->GetStringProperty("name", nodename); mitk::TensorImage* vol = static_cast((*itemiter)->GetData()); ++itemiter; typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(vol, itkvol); typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; FilterType::GradientListType gradientList; switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex()) { case 0: gradientList = MakeGradientList<12>(); break; case 1: gradientList = MakeGradientList<42>(); break; case 2: gradientList = MakeGradientList<92>(); break; case 3: gradientList = MakeGradientList<162>(); break; case 4: gradientList = MakeGradientList<252>(); break; case 5: gradientList = MakeGradientList<362>(); break; case 6: gradientList = MakeGradientList<492>(); break; case 7: gradientList = MakeGradientList<642>(); break; case 8: gradientList = MakeGradientList<812>(); break; case 9: gradientList = MakeGradientList<1002>(); break; default: gradientList = MakeGradientList<92>(); } double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble(); // DWI ESTIMATION clock.Start(); MBI_INFO << "DWI Estimation "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "DWI Estimation for %s", nodename.c_str()).toAscii()); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->SetBValue(bVal); filter->SetGradientList(gradientList); //filter->SetNumberOfThreads(1); filter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; // TENSORS TO DATATREE mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(bVal); image->SetDirections(gradientList); image->SetOriginalDirections(gradientList); image->InitializeFromVectorImage(); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); mitk::DiffusionImageMapper::SetDefaultProperties(node); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dwi"); node->SetName(newname.toAscii()); nodes.push_back(node); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp index eef9ccd480..8599a6b545 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp @@ -1,1497 +1,1500 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include "berryIWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryISelectionService.h" #include "berryConstants.h" #include "berryPlatformUI.h" // Qmitk #include "QmitkTractbasedSpatialStatisticsView.h" #include "QmitkStdMultiWidget.h" #include "mitkDataNodeObject.h" #include // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vtkFloatArray.h" #include "vtkLinearTransform.h" #include "vtkPoints.h" #include "mitkSurface.h" #include #include "vtkArrowSource.h" #include "vtkUnstructuredGrid.h" #include "vtkPointData.h" #include #include #include #include #include #include "mitkITKImageImport.h" // #include "mitkImageMapperGL2D.h" #include "mitkVolumeDataVtkMapper3D.h" #include "mitkImageAccessByItk.h" #include "mitkTensorImage.h" #include "itkDiffusionTensor3D.h" #define SEARCHSIGMA 10 /* length in linear voxel dimens { // create new ones m_PointSetNode = mitk::PointSet::New();ions */ #define MAXSEARCHLENGTH (3*SEARCHSIGMA) const std::string QmitkTractbasedSpatialStatisticsView::VIEW_ID = "org.mitk.views.tractbasedspatialstatistics"; using namespace berry; struct TbssSelListener : ISelectionListener { berryObjectMacro(TbssSelListener) TbssSelListener(QmitkTractbasedSpatialStatisticsView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundTbssRoi = false; bool foundTbss = false; bool found3dImage = false; bool found4dImage = false; bool foundFiberBundle = false; mitk::TbssRoiImage* roiImage; mitk::TbssImage* image; mitk::Image* img; mitk::FiberBundleX* fib; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types // check for valid data mitk::BaseData* nodeData = node->GetData(); if( nodeData ) { if(QString("TbssRoiImage").compare(nodeData->GetNameOfClass())==0) { foundTbssRoi = true; roiImage = static_cast(nodeData); } else if (QString("TbssImage").compare(nodeData->GetNameOfClass())==0) { foundTbss = true; image = static_cast(nodeData); } else if(QString("Image").compare(nodeData->GetNameOfClass())==0) { img = static_cast(nodeData); if(img->GetDimension() == 3) { found3dImage = true; } else if(img->GetDimension() == 4) { found4dImage = true; } } else if (QString("FiberBundleX").compare(nodeData->GetNameOfClass())==0) { foundFiberBundle = true; fib = static_cast(nodeData); } } // end CHECK nodeData != NULL } } m_View->m_Controls->m_CreateRoi->setEnabled(found3dImage); m_View->m_Controls->m_ImportFsl->setEnabled(found4dImage); if(found3dImage) { m_View->InitPointsets(); } if(foundTbss && foundTbssRoi) { m_View->Plot(image, roiImage); } if(found3dImage == true && foundFiberBundle) { m_View->PlotFiberBundle(fib, img); } } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkTractbasedSpatialStatisticsView* m_View; }; QmitkTractbasedSpatialStatisticsView::QmitkTractbasedSpatialStatisticsView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkTractbasedSpatialStatisticsView::~QmitkTractbasedSpatialStatisticsView() { } void QmitkTractbasedSpatialStatisticsView::OnSelectionChanged(std::vector nodes) { //datamanager selection changed if (!this->IsActivated()) return; // Get DataManagerSelection if (!this->GetDataManagerSelection().empty()) { mitk::DataNode::Pointer sourceImageNode = this->GetDataManagerSelection().front(); mitk::Image::Pointer sourceImage = dynamic_cast(sourceImageNode->GetData()); if (!sourceImage) { m_Controls->m_TbssImageLabel->setText( QString( sourceImageNode->GetName().c_str() ) + " is no image" ); return; } // set Text m_Controls->m_TbssImageLabel->setText( QString( sourceImageNode->GetName().c_str() ) + " (" + QString::number(sourceImage->GetDimension()) + "D)" ); } else { m_Controls->m_TbssImageLabel->setText("Please select an image"); } } void QmitkTractbasedSpatialStatisticsView::InitPointsets() { // Check if PointSetStart exsits, if not create it. m_P1 = this->GetDefaultDataStorage()->GetNamedNode("PointSetNode"); if (m_PointSetNode) { //m_PointSetNode = dynamic_cast(m_P1->GetData()); return; } if ((!m_P1) || (!m_PointSetNode)) { // create new ones m_PointSetNode = mitk::PointSet::New(); m_P1 = mitk::DataNode::New(); m_P1->SetData( m_PointSetNode ); m_P1->SetProperty( "name", mitk::StringProperty::New( "PointSet" ) ); m_P1->SetProperty( "opacity", mitk::FloatProperty::New( 1 ) ); m_P1->SetProperty( "helper object", mitk::BoolProperty::New(false) ); // CHANGE if wanted m_P1->SetProperty( "pointsize", mitk::FloatProperty::New( 0.1 ) ); m_P1->SetColor( 1.0, 0.0, 0.0 ); this->GetDefaultDataStorage()->Add(m_P1); m_Controls->m_PointWidget->SetPointSetNode(m_P1); m_Controls->m_PointWidget->SetMultiWidget(GetActiveStdMultiWidget()); } } void QmitkTractbasedSpatialStatisticsView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkTractbasedSpatialStatisticsViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); } m_SelListener = berry::ISelectionListener::Pointer(new TbssSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); m_IsInitialized = false; // Table for the FSL TBSS import m_GroupModel = new QmitkTbssTableModel(); m_Controls->m_GroupInfo->setModel(m_GroupModel); } void QmitkTractbasedSpatialStatisticsView::Activated() { QmitkFunctionality::Activated(); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTractbasedSpatialStatisticsView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTractbasedSpatialStatisticsView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_CreateRoi), SIGNAL(clicked()), this, SLOT(CreateRoi()) ); connect( (QObject*)(m_Controls->m_ImportFsl), SIGNAL(clicked()), this, SLOT(TbssImport()) ); connect( (QObject*)(m_Controls->m_AddGroup), SIGNAL(clicked()), this, SLOT(AddGroup()) ); connect( (QObject*)(m_Controls->m_RemoveGroup), SIGNAL(clicked()), this, SLOT(RemoveGroup()) ); connect( (QObject*)(m_Controls->m_Clipboard), SIGNAL(clicked()), this, SLOT(CopyToClipboard()) ); connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(selected(const QwtDoublePoint&)), SLOT(Clicked(const QwtDoublePoint&) ) ); connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(moved(const QwtDoublePoint&)), SLOT(Clicked(const QwtDoublePoint&) ) ); } } void QmitkTractbasedSpatialStatisticsView::CopyToClipboard() { std::vector > vals = m_Controls->m_RoiPlotWidget->GetVals(); QString clipboardText; for (std::vector >::iterator it = vals.begin(); it != vals.end(); ++it) { for (std::vector::iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { clipboardText.append(QString("%1 \t").arg(*it2)); double d = *it2; std::cout << d <setText(clipboardText, QClipboard::Clipboard); } void QmitkTractbasedSpatialStatisticsView::RemoveGroup() { QTableView *temp = static_cast(m_Controls->m_GroupInfo); // QSortFilterProxyModel *proxy = static_cast(temp->model()); QItemSelectionModel *selectionModel = temp->selectionModel(); QModelIndexList indices = selectionModel->selectedRows(); QModelIndex index; foreach(index, indices) { int row = index.row(); m_GroupModel->removeRows(row, 1, QModelIndex()); } } std::string QmitkTractbasedSpatialStatisticsView::ReadFile(std::string whatfile) { std::string s = "Select a" + whatfile; QFileDialog* w = new QFileDialog(this->m_Controls->m_ImportFsl, QString(s.c_str()) ); w->setFileMode(QFileDialog::ExistingFiles); w->setDirectory("/home"); if(whatfile == "gradient image") { w->setNameFilter("Tbss gradient images (*.tgi)"); } // RETRIEVE SELECTION if ( w->exec() != QDialog::Accepted ) { return ""; MITK_INFO << "Failed to load"; } QStringList filenames = w->selectedFiles(); if (filenames.size() > 0) { std::string retval = filenames.at(0).toStdString(); return retval; } return ""; } void QmitkTractbasedSpatialStatisticsView::AddGroup() { QString group("Group"); int number = 0; QPair pair(group, number); QList< QPair >list = m_GroupModel->getList(); if(!list.contains(pair)) { m_GroupModel->insertRows(0, 1, QModelIndex()); QModelIndex index = m_GroupModel->index(0, 0, QModelIndex()); m_GroupModel->setData(index, group, Qt::EditRole); index = m_GroupModel->index(0, 1, QModelIndex()); m_GroupModel->setData(index, number, Qt::EditRole); } else { //QMessageBox::information(this, "Duplicate name"); } } void QmitkTractbasedSpatialStatisticsView::TbssImport() { // Read groups from the interface mitk::TbssImporter::Pointer importer = mitk::TbssImporter::New(); QList< QPair >list = m_GroupModel->getList(); if(list.size() == 0) { QMessageBox msgBox; msgBox.setText("No study group information has been set yet."); msgBox.exec(); return; } std::vector < std::pair > groups; for(int i=0; i pair = list.at(i); std::string s = pair.first.toStdString(); int n = pair.second; std::pair p; p.first = s; p.second = n; groups.push_back(p); } importer->SetGroupInfo(groups); std::string minfo = m_Controls->m_MeasurementInfo->text().toStdString(); importer->SetMeasurementInfo(minfo); std::string name = ""; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(node->GetData()); if(img->GetDimension() == 4) { importer->SetImportVolume(img); name = node->GetName(); } } } } mitk::TbssImage::Pointer tbssImage; tbssImage = importer->Import(); name += "_tbss"; AddTbssToDataStorage(tbssImage, name); } void QmitkTractbasedSpatialStatisticsView::AddTbssToDataStorage(mitk::Image* image, std::string name) { mitk::LevelWindow levelwindow; levelwindow.SetAuto( image ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "name", mitk::StringProperty::New(name) ); result->SetData( image ); result->SetProperty( "levelwindow", levWinProp ); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result ); // show the results mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkTractbasedSpatialStatisticsView::Clicked(const QwtDoublePoint& pos) { if(m_Roi.size() > 0 && m_CurrentGeometry != NULL) { int index = (int)pos.x(); - index = std::max(0, index); - index = std::min(index, (int)m_Roi.size()); + + + index = std::min( (int)m_Roi.size()-1, std::max(0, index) ); + + itk::Index<3> ix = m_Roi.at(index); mitk::Vector3D i; i[0] = ix[0]; i[1] = ix[1]; i[2] = ix[2]; mitk::Vector3D w; m_CurrentGeometry->IndexToWorld(i, w); mitk::Point3D origin = m_CurrentGeometry->GetOrigin(); mitk::Point3D p; p[0] = w[0] + origin[0]; p[1] = w[1] + origin[1]; p[2] = w[2] + origin[2]; m_MultiWidget->MoveCrossToPosition(p); m_Controls->m_RoiPlotWidget->drawBar(index); } } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTractbasedSpatialStatisticsView::AdjustPlotMeasure(const QString & text) { berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTractbasedSpatialStatisticsView::Clustering() { /* // Create a mask using the distance map typedef itk::ImageFileReader< VectorImageType > DirectionReader; DirectionReader::Pointer directionReader = DirectionReader::New(); directionReader->SetFileName(m_TbssWorkspaceManager.GetInputDir().toStdString() + "/tbss/" + m_TbssWorkspaceManager.GetGradient().toStdString()); directionReader->Update(); VectorImageType::Pointer directions = directionReader->GetOutput(); FloatReaderType::Pointer distMapReader = FloatReaderType::New(); distMapReader->SetFileName(m_TbssWorkspaceManager.GetInputDir().toStdString() + "/stats/" + m_TbssWorkspaceManager.GetDistanceMap().toStdString()); distMapReader->Update(); FloatImageType::Pointer distanceMap = distMapReader->GetOutput(); std::string line; std::string path = "/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/rois/cc.txt"; std::ifstream file(path.c_str()); std::vector< itk::Index< 3 > > roi; if(file.is_open()) { while(getline(file,line)) { std::vector tokens; Tokenize(line, tokens); itk::Index<3> ix; ix[0] = atoi(tokens[0].c_str()); ix[1] = atoi(tokens[1].c_str()); ix[2] = atoi(tokens[2].c_str()); roi.push_back(ix); } } if(roi.size() == 0) { return; } // Some code from the projection algorithm of tbss to create a mask std::vector< std::vector< itk::Index< 3 > > > rois; for(int j=0; j > indices; FloatImageType::SizeType size = distanceMap->GetLargestPossibleRegion().GetSize(); bool roiDone = false; while(!roiDone && j ix = roi[j]; int x=ix[0]; int y=ix[1]; int z=ix[2]; VectorImageType::PixelType dir = directions->GetPixel(ix); indices.push_back(ix); for(int iters=0;iters<2;iters++) { float distance=0; for(int d=1;d=size[0] && dy<=size[1] && dz<=size[2]) { d=MAXSEARCHLENGTH; } else if(distanceMap->GetPixel(ix)>=distance) { distance = distanceMap->GetPixel(ix); indices.push_back(ix); } else{ d=MAXSEARCHLENGTH; } } } j++; } // Create a mask from indices UCharImageType::Pointer maskItk = UCharImageType::New(); maskItk->SetRegions(distanceMap->GetRequestedRegion()); maskItk->SetDirection(distanceMap->GetDirection()); maskItk->SetSpacing(distanceMap->GetSpacing()); maskItk->SetOrigin(distanceMap->GetOrigin()); maskItk->Allocate(); // For every point on the roi create a mask and feed it to the partial voluming algorithm //maskItk->FillBuffer(0); // Create a bounding box from current ROI int xMin = numeric_limits::max(); int yMin = numeric_limits::max(); int zMin = numeric_limits::max(); int xMax = numeric_limits::min(); int yMax = numeric_limits::min(); int zMax = numeriUCharImageType::Pointer newMask = UCharImageType::New();c_limits::min(); for(int i=0; i ix = indices[i]; if(ix[0] < xMin) xMin=ix[0]; if(ix[1] < yMin) yMin=ix[1]; if(ix[2] < zMin) zMin=ix[2]; if(ix[0] > xMax) xMax=ix[0]; if(ix[1] > yMax) yMax=ix[1]; if(ix[2] > zMax) zMax=ix[2]; } FloatImageType::PointType origin = distanceMap->GetOrigin(); CharImageType::PointType originMask; originMask[0] = origin[0] + xMin; originMask[1] = origin[1] + -yMin; originMask[2] = origin[2] + zMin; CharImageType::RegionType region; CharImageType::RegionType::SizeType s; s[0] = xMax-xMin + 1; s[1] = yMax-yMin + 1; s[2] = zMax-zMin + 1; region.SetSize(s); UCharImageType::Pointer newMask = UCharImageType::New(); newMask->SetSpacing( distanceMap->GetSpacing() ); // Set the image spacing newMask->SetOrigin( originMask ); // Set the image origin newMask->SetDirection( distanceMap->GetDirection() ); // Set the image direction newMask->SetRegions( region ); newMask->Allocate(); newMask->FillBuffer(0); for(int i=0; i ix = indices[i]; itk::Point< double, 3 > point; itk::Index< 3 > index; distanceMap->TransformIndexToPhysicalPoint (ix, point); newMask->TransformPhysicalPointToIndex(point, index); newMask->SetPixel(index, 1); } */ /* UCharImageType::Pointer newMask = UCharImageType::New(); UCharReaderType::Pointer cReader = UCharReaderType::New(); cReader->SetFileName("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/ClusteringFornix/fornix_central_maxFA_path_Dilated_by_3.nrrd"); cReader->Update(); newMask = cReader->GetOutput(); // mitk::DataNode::Pointer maskNode = readNode("itk image/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/clusterMasks/area2.nii"); // mitk::Image::Pointer mask = dynamic_cast(maskNode->GetData()); mitk::Image::Pointer mask; mitk::CastToMitkImage(newMask, mask); typedef mitk::PartialVolumeAnalysisHistogramCalculator HistorgramCalculator; typedef mitk::PartialVolumeAnalysisClusteringCalculator ClusteringType; typedef HistorgramCalculator::HistogramType HistogramType; HistorgramCalculator::Pointer histogramCalculator = HistorgramCalculator::New(); // Make list of subjects std::vector paths; paths.push_back("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/FA/SORTEDBYCONDITION/FA/subset"); // paths.push_back("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/FA/SORTEDBYCONDITION/AXD/"); for(int j=0; j values; for(int i=0; i(node->GetData()); histogramCalculator->SetImage(image); histogramCalculator->SetImageMask( mask ); histogramCalculator->SetMaskingModeToImage(); histogramCalculator->SetNumberOfBins(25); histogramCalculator->SetUpsamplingFactor(5); histogramCalculator->SetGaussianSigma(0.0); histogramCalculator->SetForceUpdate(true); bool statisticsChanged = histogramCalculator->ComputeStatistics( ); ClusteringType::ParamsType *cparams = 0; ClusteringType::ClusterResultType *cresult = 0; ClusteringType::HistType *chist = 0; ClusteringType::HelperStructPerformClusteringRetval *currentPerformClusteringResults; try{ mitk::Image* tmpImg = histogramCalculator->GetInternalImage(); mitk::Image::ConstPointer imgToCluster = tmpImg; if(imgToCluster.IsNotNull()) { // perform clustering const HistogramType *histogram = histogramCalculator->GetHistogram( ); ClusteringType::Pointer clusterer = ClusteringType::New(); clusterer->SetStepsNumIntegration(200); clusterer->SetMaxIt(1000); mitk::Image::Pointer pFiberImg; currentPerformClusteringResults = clusterer->PerformClustering(imgToCluster, histogram, 2); pFiberImg = currentPerformClusteringResults->clusteredImage; cparams = currentPerformClusteringResults->params; cresult = currentPerformClusteringResults->result; chist = currentPerformClusteringResults->hist; // m_Controls->m_HistogramWidget->SetParameters( // cparams, cresult, chist ); std::vector *xVals = chist->GetXVals(); std::vector *fiberVals = new std::vector(cresult->GetFiberVals()); double fiberFA = 0.0; double weights = 0.0; // std::cout << "x, y, fiber, nonFiber, mixed, combi" << std::endl; for(int k=0; ksize(); ++k) { fiberFA += xVals->at(k) * fiberVals->at(k); weights += fiberVals->at(k); } fiberFA = fiberFA / weights; std::cout << "FA: " << fiberFA << std::endl; values.push_back(fiberFA); } } catch ( const std::runtime_error &e ) { std::cout << "noooooooooooooooooooooooooooooooo!"; } //MITK_INFO << "number of voxels: " << indices.size(); } std::vector::iterator it = values.begin(); while(it!=values.end()) { std::cout << *it << std::endl; ++it; } }*/ } void QmitkTractbasedSpatialStatisticsView::CreateRoi() { // It is important to load the MeanFASkeletonMask image in MITK to make sure that point selection and // pathfinding is done on the same image //string filename = m_TbssWorkspaceManager.GetInputDir().toStdString() + "/stats/" + m_TbssWorkspaceManager.GetMeanFASkeletonMask().toStdString(); // Implement a way to obtain skeleton and skeletonFA without sml workspace double threshold = QInputDialog::getDouble(m_Controls->m_CreateRoi, tr("Set an FA threshold"), tr("Threshold:"), QLineEdit::Normal, 0.2); mitk::Image::Pointer image; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(node->GetData()); if(img->GetDimension() == 3) { image = img; } } } } if(image.IsNull()) { return; } mitk::TractAnalyzer analyzer; analyzer.SetInputImage(image); analyzer.SetThreshold(threshold); int n = 0; if(m_PointSetNode.IsNotNull()) { n = m_PointSetNode->GetSize(); if(n==0) { QMessageBox msgBox; msgBox.setText("No points have been set yet."); msgBox.exec(); } } else{ QMessageBox msgBox; msgBox.setText("No points have been set yet."); msgBox.exec(); } std::string pathDescription = ""; std::vector< itk::Index<3> > totalPath; if(n>0) { for(int i=0; iGetPoint(i); mitk::Point3D p2 = m_PointSetNode->GetPoint(i+1); itk::Index<3> StartPoint; mitk::ProgressBar::GetInstance()->Progress(); itk::Index<3> EndPoint; image->GetGeometry()->WorldToIndex(p,StartPoint); image->GetGeometry()->WorldToIndex(p2,EndPoint); MITK_INFO << "create roi"; analyzer.BuildGraph(StartPoint, EndPoint); std::vector< itk::Index<3> > path = analyzer.GetPath(); for(std::vector< itk::Index<3> >::iterator it = path.begin(); it != path.end(); it++) { itk::Index<3> ix = *it; if (!(ix==EndPoint)) { mitk::ProgressBar::GetInstance()->Progress(); totalPath.push_back(ix); std::stringstream ss; ss << ix[0] << " " << ix[1] << " " << ix[2] << "\n"; pathDescription += ss.str(); } else { // Only when dealing with the last segment the last point should be added. This one will not occur // as the first point of the next roi segment. if(i == (n-2)) { totalPath.push_back(EndPoint); std::stringstream ss; ss << EndPoint[0] << " " << EndPoint[1] << " " << EndPoint[2] << "\n"; pathDescription += ss.str(); } } } } m_Controls->m_PathTextEdit->setPlainText(QString(pathDescription.c_str())); FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(image, itkImg); CharImageType::Pointer roiImg = CharImageType::New(); roiImg->SetRegions(itkImg->GetLargestPossibleRegion().GetSize()); roiImg->SetOrigin(itkImg->GetOrigin()); roiImg->SetSpacing(itkImg->GetSpacing()); roiImg->SetDirection(itkImg->GetDirection()); roiImg->Allocate(); roiImg->FillBuffer(0); std::vector< itk::Index<3> > roi; std::vector< itk::Index<3> >::iterator it; for(it = totalPath.begin(); it != totalPath.end(); it++) { itk::Index<3> ix = *it; roiImg->SetPixel(ix, 1); roi.push_back(ix); } mitk::TbssRoiImage::Pointer tbssRoi = mitk::TbssRoiImage::New(); //mitk::CastToTbssImage(m_CurrentRoi.GetPointer(), tbssRoi); tbssRoi->SetRoi(roi); tbssRoi->SetImage(roiImg); tbssRoi->SetStructure(m_Controls->m_Structure->text().toStdString()); tbssRoi->InitializeFromImage(); // mitk::Image::Pointer tbssRoi = mitk::Image::New(); //mitk::CastToTbssImage(m_CurrentRoi.GetPointer(), tbssRoi); // mitk::CastToMitkImage(roiImg, tbssRoi); AddTbssToDataStorage(tbssRoi, m_Controls->m_RoiName->text().toStdString()); } } void QmitkTractbasedSpatialStatisticsView::PlotFiberBundle(mitk::FiberBundleX *fib, mitk::Image* img) { int num = fib->GetNumFibers(); std::cout << "number of fibers: " << num << std::endl; vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkCellArray* lines = fiberPolyData->GetLines(); lines->InitTraversal(); int lineSize = lines->GetSize(); std::cout << "line size: " << lineSize << std::cout; typedef itk::Point PointType; typedef std::vector< PointType> TractType; typedef std::vector< TractType > TractContainerType; TractContainerType tracts; for( int fiberID( 0 ); fiberID < num; fiberID++ ) { vtkIdType numPointsInCell(0); vtkIdType* pointsInCell(NULL); lines->GetNextCell ( numPointsInCell, pointsInCell ); TractType singleTract; for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) { // push back point double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); PointType point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); } tracts.push_back(singleTract); } m_Controls->m_RoiPlotWidget->PlotFiberBundles(tracts, img); } void QmitkTractbasedSpatialStatisticsView::Plot(mitk::TbssImage* image, mitk::TbssRoiImage* roiImage) { if(m_Controls->m_TabWidget->currentWidget() == m_Controls->m_MeasureTAB) { std::vector< itk::Index<3> > roi = roiImage->GetRoi(); m_Roi = roi; m_CurrentGeometry = image->GetGeometry(); std::string resultfile = ""; /* if(image->GetPreprocessedFA()) { resultFile = image->GetPreprocessedFAFile(); } */ std::string structure = roiImage->GetStructure(); //m_View->m_CurrentGeometry = image->GetGeometry(); m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo()); // Check for preprocessed results to save time //if(resultfile == "") // { // Need to calculate the results using the 4D volume // Can save the time this takes if there are results available already //std::string type = m_Controls->m_MeasureType->itemText(m_Controls->m_MeasureType->currentIndex()).toStdString(); m_Controls->m_RoiPlotWidget->SetProjections(image->GetImage()); // } m_Controls->m_RoiPlotWidget->SetRoi(roi); m_Controls->m_RoiPlotWidget->SetStructure(structure); m_Controls->m_RoiPlotWidget->SetMeasure( image->GetMeasurementInfo() ); m_Controls->m_RoiPlotWidget->DrawProfiles(resultfile); } } void QmitkTractbasedSpatialStatisticsView::Masking() { //QString filename = m_Controls->m_WorkingDirectory->text(); QString filename = "E:/Experiments/tbss"; QString faFiles = filename + "/AxD"; QString maskFiles = filename + "/bin_masks"; QDirIterator faDirIt(faFiles, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); QDirIterator maskDirIt(maskFiles, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); std::vector faFilenames; std::vector maskFilenames; std::vector outputFilenames; while(faDirIt.hasNext() && maskDirIt.hasNext()) { faDirIt.next(); maskDirIt.next(); if((faDirIt.fileInfo().completeSuffix() == "nii" || faDirIt.fileInfo().completeSuffix() == "mhd" || faDirIt.fileInfo().completeSuffix() == "nii.gz") && (maskDirIt.fileInfo().completeSuffix() == "nii" || maskDirIt.fileInfo().completeSuffix() == "mhd" || maskDirIt.fileInfo().completeSuffix() == "nii.gz")) { faFilenames.push_back(faDirIt.filePath().toStdString()); outputFilenames.push_back(faDirIt.fileName().toStdString()); maskFilenames.push_back(maskDirIt.filePath().toStdString()); } } std::vector::iterator faIt = faFilenames.begin(); std::vector::iterator maskIt = maskFilenames.begin(); std::vector::iterator outputIt = outputFilenames.begin(); // Now multiply all FA images with their corresponding masks QString outputDir = filename; while(faIt != faFilenames.end() && maskIt != maskFilenames.end() && outputIt != outputFilenames.end()) { std::cout << "Mask " << *faIt << " with " << *maskIt << std::endl; typedef itk::MultiplyImageFilter MultiplicationFilterType; FloatReaderType::Pointer floatReader = FloatReaderType::New(); CharReaderType::Pointer charReader = CharReaderType::New(); floatReader->SetFileName(*faIt); //floatReader->Update(); //FloatImageType::Pointer faImage = floatReader->GetOutput(); charReader->SetFileName(*maskIt); //charReader->Update(); // CharImageType::Pointer maskImage = charReader->GetOutput(); MultiplicationFilterType::Pointer multiplicationFilter = MultiplicationFilterType::New(); multiplicationFilter->SetInput1(floatReader->GetOutput()); multiplicationFilter->SetInput2(charReader->GetOutput()); multiplicationFilter->Update(); //FloatImageType::Pointer maskedImage = FloatImageType::New(); //maskedImage = MultiplicationFilter->GetOutput(); FloatWriterType::Pointer floatWriter = FloatWriterType::New(); std::string s = faFiles.toStdString().append("/"+*outputIt); floatWriter->SetFileName(s.c_str()); floatWriter->SetInput(multiplicationFilter->GetOutput()); floatWriter->Update(); ++faIt; ++maskIt; ++outputIt; } } VectorImageType::Pointer QmitkTractbasedSpatialStatisticsView::ConvertToVectorImage(mitk::Image::Pointer mitkImage) { VectorImageType::Pointer vecImg = VectorImageType::New(); mitk::Geometry3D* geo = mitkImage->GetGeometry(); mitk::Vector3D spacing = geo->GetSpacing(); mitk::Point3D origin = geo->GetOrigin(); VectorImageType::SpacingType vecSpacing; vecSpacing[0] = spacing[0]; vecSpacing[1] = spacing[1]; vecSpacing[2] = spacing[2]; VectorImageType::PointType vecOrigin; vecOrigin[0] = origin[0]; vecOrigin[1] = origin[1]; vecOrigin[2] = origin[2]; VectorImageType::SizeType size; size[0] = mitkImage->GetDimension(0); size[1] = mitkImage->GetDimension(1); size[2] = mitkImage->GetDimension(2); vecImg->SetSpacing(vecSpacing); vecImg->SetOrigin(vecOrigin); vecImg->SetRegions(size); vecImg->SetVectorLength(mitkImage->GetDimension(3)); vecImg->Allocate(); for(int x=0; x pixel = vecImg->GetPixel(ix); for (int t=0; tGetPixelValueByIndex(ix, t); pixel.SetElement(t, f); } vecImg->SetPixel(ix, pixel); } } } return vecImg; } /* void QmitkTractbasedSpatialStatisticsView::InitializeGridByVectorImage() { // Read vector image from file typedef itk::ImageFileReader< FloatVectorImageType > VectorReaderType; VectorReaderType::Pointer vectorReader = VectorReaderType::New(); vectorReader->SetFileName("E:\\tbss\\testing\\Gradient.mhd"); vectorReader->Update(); FloatVectorImageType::Pointer directions = vectorReader->GetOutput(); // Read roi from file. CharReaderType::Pointer roiReader = CharReaderType::New(); roiReader->SetFileName("E:\\tbss\\testing\\debugging skeletonization\\segment2.mhd"); roiReader->Update(); CharImageType::Pointer roi = roiReader->GetOutput(); DoInitializeGridByVectorImage(directions, roi, std::string("directions")); } void QmitkTractbasedSpatialStatisticsView::DoInitializeGridByVectorImage(FloatVectorImageType::Pointer vectorpic, CharImageType::Pointer roi, std::string name) { //vtkStructuredGrid* grid = vtkStructuredGrid::New(); itk::Matrix itkdirection = vectorpic->GetDirection(); itk::Matrix itkinversedirection = itk::Matrix(itkdirection.GetInverse()); std::vector GridPoints; vtkPoints *points = vtkPoints::New(); mitk::Geometry3D::Pointer geom = mitk::Geometry3D::New(); vtkLinearTransform *vtktransform; vtkLinearTransform *inverse; mitk::Image::Pointer geomget = mitk::Image::New(); geomget->InitializeByItk(vectorpic.GetPointer()); geom = geomget->GetGeometry(); vtktransform = geom->GetVtkTransform(); inverse = vtktransform->GetLinearInverse(); vtkFloatArray * directions = vtkFloatArray::New(); directions->SetName("Vectors"); directions->SetNumberOfComponents(3); // Iterator for the vector image itk::ImageRegionIterator it_input(vectorpic, vectorpic->GetLargestPossibleRegion()); FloatVectorType nullvector; nullvector.Fill(0); double lengthsum = 0; int id = 0; // Iterator for the roi itk::ImageRegionIterator roiIt(roi, roi->GetLargestPossibleRegion()); roiIt.GoToBegin(); for(it_input.GoToBegin(); !( it_input.IsAtEnd() || roiIt.IsAtEnd() ); ++it_input) { //VectorType val = it_input.Value(); if(it_input.Value() != nullvector && roiIt.Get() != 0) { //itk::Point point; mitk::Point3D mitkpoint, mitkworldpoint; mitk::Point3D mitkendpoint, mitkworldendpoint; mitk::Vector3D mitkvector, mitktransvector; itk::Point direction = it_input.Value().GetDataPointer(); //itk::Index<3> in_input = it_input.GetIndex(); //itk::ContinuousIndex cindirection; FloatVectorType transvec = it_input.Value(); mitkvector[0] = transvec[0]; mitkvector[1] = transvec[1]; mitkvector[2] = transvec[2]; //mitkvector[2] = 0.0; mitkpoint[0] = it_input.GetIndex()[0]; mitkpoint[1] = it_input.GetIndex()[1]; mitkpoint[2] = it_input.GetIndex()[2]; mitkendpoint[0] = mitkpoint[0] + mitkvector[0]; mitkendpoint[1] = mitkpoint[1] + mitkvector[1]; mitkendpoint[2] = mitkpoint[2] + mitkvector[2]; //mitkpoint.setXYZ((ScalarType)point[0],(ScalarType)point[1],(ScalarType)point[2]); geom->IndexToWorld(mitkpoint, mitkworldpoint); geom->IndexToWorld(mitkendpoint, mitkworldendpoint); mitktransvector[0] = mitkworldendpoint[0] - mitkworldpoint[0]; mitktransvector[1] = mitkworldendpoint[1] - mitkworldpoint[1]; mitktransvector[2] = mitkworldendpoint[2] - mitkworldpoint[2]; lengthsum += mitktransvector.GetNorm(); directions->InsertTuple3(id,mitktransvector[0],mitktransvector[1],mitktransvector[2]); points->InsertPoint(id,mitkworldpoint[0],mitkworldpoint[1],mitkworldpoint[2]); id++; //for (unsigned short loop = 0; (loop < 20) && (!it_input.IsAtEnd()); loop++) //{ // ++it_input; //} if(it_input.IsAtEnd()) { break; } } ++roiIt; } double meanlength = lengthsum / id; vtkGlyph3D* glyph = vtkGlyph3D::New(); vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); ugrid->SetPoints(points); ugrid->GetPointData()->SetVectors(directions); glyph->SetInput(ugrid); glyph->SetScaleModeToScaleByVector(); glyph->SetScaleFactor(0.5); glyph->SetColorModeToColorByScalar(); //glyph->ClampingOn(); vtkArrowSource* arrow = vtkArrowSource::New(); if(meanlength > 5) {arrow->SetTipLength(0);arrow->SetTipRadius(0);} arrow->SetShaftRadius(0.03/meanlength); //arrow->SetTipRadius(0.05/meanlength); glyph->SetSource(arrow->GetOutput()); glyph->Update(); mitk::Surface::Pointer glyph_surface = mitk::Surface::New(); glyph_surface->SetVtkPolyData(glyph->GetOutput()); glyph_surface->UpdateOutputInformation(); mitk::DataNode::Pointer gridNode = mitk::DataNode::New(); gridNode->SetProperty( "name", mitk::StringProperty::New(name.c_str()) ); //m_GridNode->SetProperty( "color" , m_GridColor); gridNode->SetProperty( "visible", mitk::BoolProperty::New(true) ); gridNode->SetProperty( "segmentation", mitk::BoolProperty::New(true) ); gridNode->SetProperty( "ID-Tag", mitk::StringProperty::New("grid") ); gridNode->SetProperty( "shader", mitk::StringProperty::New("mitkShaderLightning") ); gridNode->SetData( glyph_surface ); GetDefaultDataStorage()->Add(gridNode); } */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h index a4ad94b217..a7b2cb6975 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h @@ -1,94 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef _QEMBED_1804289383 #define _QEMBED_1804289383 #include #include static const QRgb QmitkDiffusionTensorEstimation_data[] = { 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3c001eea,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x1a0a1d00,0x611a1800,0x8c311200,0x883c000d,0x55300051, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x621a1700,0xdd171200,0xfe341600,0xfe6b1400,0xf9960d00,0xf6b21600,0x6eb01000,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x1ace0014,0x27d10d00,0x3aaff00,0x3aaff00, 0x3aaff00,0x8a110f00,0xf40d0f00,0xf7341400,0xef6b0f00,0xf19d1200,0xf3c51200,0xf2e60c00,0xefe91000,0x40c70c00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3fca0c00,0x3aaff00,0x3aaff00,0x81121000,0xfb0f1100,0xf1251100, 0xf05b1000,0xf38c1600,0xf2b80e00,0xf6df1800,0xedfc0400,0xf5ff1400,0xb3f41100,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x35f10e00,0x561b1800,0xf40d0f00,0xf0181000,0xee451000,0xef761100,0xeea30c00,0xeece0a00, 0xdef40e00,0xd7ff1400,0xf5ff1400,0xebfd1700,0x1ded2300,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x38760e00,0xe51a1000,0xf6131400,0xf2331200,0xf4651300,0xf38c1600,0xf5b31700,0xffd11a11,0xfff52d21,0xffff3928,0xffff1d0a, 0xf5ff1400,0x44ec1a00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x86110f00,0xfa0e1100,0xee190f00,0xf24d1100,0xf0751100,0xf19d1200,0xf6c30f00,0xffdf1e12,0xffff5749,0xffff6f5f,0xffff2016,0xf5ff1400,0x55fc0f00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x23071600,0xe7121300,0xf6131400,0xf2331200, 0xef5c1000,0xee850e00,0xf1a91400,0xeece0a00,0xffee251c,0xfffe8272,0xfffe9080,0xffff2d1f,0xf5ff1400,0x5fff1500,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x7a131100,0xfb0f1100,0xee190f00,0xef430f00,0xee6b0f00,0xef911000,0xf4b41700, 0xf3d41600,0xfff62f22,0xffff8575,0xffff7d6b,0xffff2016,0xf5ff1400,0x47ff0700,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xc70e1200,0xfc161600,0xef251000,0xee510e00,0xee7a0c00,0xf19d1200,0xf0bb1000,0xeddd0d00,0xfffa3325,0xfffe6d5d, 0xffff5543,0xffff2016,0xf5ff1400,0x35f10e00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x2e270600,0xf0111200,0xf2151100,0xf0361000,0xed600c00,0xee850e00,0xf4a71500,0xf3c51200,0xf4e40b00,0xffff2d1f,0xffff4639,0xffff3021,0xffff1d0a,0xe0ff1000, 0x9c61c00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x5339900,0x1000df10,0x180bd400,0x70093b00,0xf9101700,0xf0181000, 0xef430f00,0xef6b0f00,0xf1900f00,0xefae0e00,0xeece0a00,0xefe91000,0xeaff0a00,0xe9ff0b00,0xf5ff1400,0xf5ff1400,0xcbf11d00,0x3912ce00,0x3912ce00,0x3912ce00, 0x3005c500,0x3812d100,0x3c00d50d,0x3005c500,0x2e06d300,0x2e06d300,0x2e06d300,0x2c06dc00,0x9e0d3f00,0xf70b1700,0xf1251100,0xef4e1100,0xf0751100,0xf39a1100, 0xf3b80e00,0xf6d01400,0xefe91000,0xeaff0a00,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x7ef71000,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xa90c0c00,0xf70d1100,0xf32f1400,0xf15b1000,0xf2801200,0xf09d1200,0xf0bb1000,0xf1d80800,0xefe91000, 0xf5ff1400,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x2ffa1b00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0xb9151100,0xfc161600,0xef361000,0xf2651200,0xee850e00,0xf4a71500,0xf4c41100,0xeedc0c00,0xf5f10f00,0xf5ff1400,0xf5ff1400,0xf5ff1400, 0xb6ff1400,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xb8151100, 0xfa181400,0xf2401300,0xef6a0e00,0xf28e0f00,0xf0ad0d00,0xf3c51200,0xf6df1800,0xf4f21100,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x45fb1200,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xa4191400,0xfd1a1500,0xef430f00,0xf3701500, 0xef911000,0xefae0e00,0xeece0a00,0xf6df1800,0xf4f21100,0xf0fa0100,0xfcfa0c00,0xa7f91200,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x7c131000,0xff1b1600,0xf54a1600,0xf1741100,0xf49a1100,0xf4b41700,0xeece0a00, 0xf2e60c00,0xf4f21100,0xf5ff1400,0xeaf10400,0x27f80007,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x37050e00,0xf2151100,0xf54a1600,0xf0751100,0xf29b1200,0xf2b80e00,0xf6d01400,0xf2e60c00,0xf5f10f00,0xf1f51200, 0x68f00c00,0x2cb90600,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0xb4171200,0xfb421100,0xf0751100,0xf29b1200,0xf1b90f00,0xf6d01400,0xf4e40b00,0xfce91a00,0x66eb1400,0x3aaff00,0x31c60005,0x1ace0014, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x2b061200, 0xd8321100,0xfa6f0e00,0xf7970e00,0xf5b50b00,0xfbcc0f00,0xdbd91500,0x50d20d00,0x3aaff00,0x3aaff00,0x3aaff00,0x3fca0c00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x23330700,0xa3430010,0xbc890e00, 0xbaaa1600,0x6dbd0c00,0x1bd03900,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x21d11700,0x2ed30006,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x56600cc,0x2b002af9,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x37cc0009,0xab31900,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x2d0600d2,0x18002adf,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00, 0x3aaff00,0x3aaff00,0xeed0000,0x3cd50d00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00 }; /* Generated by qembed */ static struct EmbedImage { int width, height, depth; const unsigned char *data; int numColors; const QRgb *colorTable; bool alpha; const char *name; } embed_image_vec[] = { { 25, 25, 32, (const unsigned char*)QmitkDiffusionTensorEstimation_data, 0, 0, TRUE, "QmitkDiffusionTensorEstimation" }, { 0, 0, 0, 0, 0, 0, 0, 0 } }; static const QImage& qembed_findImage( const QString& name ) { static QDict dict; QImage* img = dict.find( name ); if ( !img ) { - for ( int i = 0; embed_image_vec[i].data; i++ ) { - if ( strcmp(embed_image_vec[i].name, name.latin1()) == 0 ) { - img = new QImage((uchar*)embed_image_vec[i].data, - embed_image_vec[i].width, - embed_image_vec[i].height, - embed_image_vec[i].depth, - (QRgb*)embed_image_vec[i].colorTable, - embed_image_vec[i].numColors, - QImage::BigEndian ); - if ( embed_image_vec[i].alpha ) - img->setAlphaBuffer( TRUE ); - dict.insert( name, img ); - break; - } - } - if ( !img ) { - static QImage dummy; - return dummy; - } + for ( int i = 0; embed_image_vec[i].data; i++ ) { + if ( strcmp(embed_image_vec[i].name, name.latin1()) == 0 ) { + img = new QImage((uchar*)embed_image_vec[i].data, + embed_image_vec[i].width, + embed_image_vec[i].height, + embed_image_vec[i].depth, + (QRgb*)embed_image_vec[i].colorTable, + embed_image_vec[i].numColors, + QImage::BigEndian ); + if ( embed_image_vec[i].alpha ) + img->setAlphaBuffer( TRUE ); + dict.insert( name, img ); + break; + } + } + if ( !img ) { + static QImage dummy; + return dummy; + } } return *img; } #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp index 4df517ea27..50f76f44a1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp @@ -1,56 +1,71 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "src/internal/QmitkDiffusionImagingPublicPerspective.h" #include "src/internal/QmitkQBallReconstructionView.h" #include "src/internal/QmitkPreprocessingView.h" #include "src/internal/QmitkDiffusionDicomImportView.h" #include "src/internal/QmitkDiffusionQuantificationView.h" #include "src/internal/QmitkTensorReconstructionView.h" #include "src/internal/QmitkControlVisualizationPropertiesView.h" #include "src/internal/QmitkODFDetailsView.h" #include "src/internal/QmitkGibbsTrackingView.h" #include "src/internal/QmitkStochasticFiberTrackingView.h" #include "src/internal/QmitkFiberProcessingView.h" #include "src/internal/QmitkFiberBundleDeveloperView.h" #include "src/internal/QmitkPartialVolumeAnalysisView.h" #include "src/internal/QmitkIVIMView.h" #include "src/internal/QmitkTractbasedSpatialStatisticsView.h" #include "src/internal/QmitkTbssSkeletonizationView.h" #include "src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingPublicPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkQBallReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDicomImport, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionQuantificationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTensorReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkControlVisualizationPropertiesView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkODFDetailsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStochasticFiberTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberBundleDeveloperView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPartialVolumeAnalysisView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIVIMView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTractbasedSpatialStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTbssSkeletonizationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkBrainNetworkAnalysisView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimaging, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h index 0436a647ad..ca951ddd3f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.cpp index 04dcc99434..ad8c56689a 100644 --- a/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.cpp @@ -1,33 +1,48 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "src/internal/colourimageprocessing/QmitkColourImageProcessingView.h" #include "src/internal/isosurface/QmitkIsoSurface.h" #include "src/internal/simpleexample/QmitkSimpleExampleView.h" #include "src/internal/simplemeasurement/QmitkSimpleMeasurement.h" #include "src/internal/viewinitialization/QmitkViewInitializationView.h" #include "src/internal/volumetry/QmitkVolumetryView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkColourImageProcessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIsoSurface, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleExampleView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleMeasurement, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkViewInitializationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkVolumetryView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_examples, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.h index 0436a647ad..ca951ddd3f 100644 --- a/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.examples/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.cpp index be8842ce21..1ae9d38d2b 100644 --- a/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "src/internal/videoplayer/QmitkVideoPlayer.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkVideoPlayer, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_examplesopencv, mitk::PluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.h index c4b9e7885d..179331f8af 100644 --- a/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.examplesopencv/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igtexamples/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.igtexamples/documentation/UserManual/Manual.dox index fdf50c060e..13d7f57fd2 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/documentation/UserManual/Manual.dox +++ b/Plugins/org.mitk.gui.qt.igtexamples/documentation/UserManual/Manual.dox @@ -1,12 +1,12 @@ /** -\bundlemainpage{org_mitk_gui_qt_igtexample} IgtExample +\bundlemainpage{org_mitk_gui_qt_igtexample} IGT Examples This bundle includes views with examples and help applications for IGT. The different views are described on the pages below:
  • \subpage org_igttrackinglab
  • \subpage org_imageguidedtherapytutorial
*/ diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.cpp index d2d5f40688..bb204dac12 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.cpp @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "QmitkIGTTutorialView.h" #include "QmitkIGTTrackingLabView.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkIGTTutorialView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIGTTrackingLabView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_igtexamples, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.h index fbd2b87367..4a81939ee0 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.cpp b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.cpp index b880d903f1..b17a1ed35f 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.cpp @@ -1,20 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkImageCropperPluginActivator.h" #include "QmitkImageCropper.h" #include namespace mitk { void ImageCropperPluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS( QmitkImageCropper, context ) } void ImageCropperPluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_imagecropper, mitk::ImageCropperPluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.h b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.h index d1b1bc334f..615c3627da 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/mitkImageCropperPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include namespace mitk { class ImageCropperPluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.cpp b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.cpp index 44124d0888..624a2b18e0 100644 --- a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkImageNavigatorPluginActivator.h" #include "QmitkImageNavigatorView.h" #include namespace mitk { void ImageNavigatorPluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkImageNavigatorView, context) } void ImageNavigatorPluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_imagenavigator, mitk::ImageNavigatorPluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.h b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.h index 75e38976c5..9498cf4a2f 100644 --- a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/mitkImageNavigatorPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKIMAGENAVIGATORPLUGINACTIVATOR_H #define MITKIMAGENAVIGATORPLUGINACTIVATOR_H #include namespace mitk { class ImageNavigatorPluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // ImageNavigatorPluginActivator } #endif // MITKIMAGENAVIGATORPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.cpp b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.cpp index 4b302006d9..4166af0e23 100644 --- a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkMaterialEditorPluginActivator.h" #include "QmitkMITKSurfaceMaterialEditorView.h" #include namespace mitk { void MaterialEditorPluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMITKSurfaceMaterialEditorView, context) } void MaterialEditorPluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_materialeditor, mitk::MaterialEditorPluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.h b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.h index fa8dfef736..0f3ebd15b0 100644 --- a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/mitkMaterialEditorPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKMATERIALEDITORPLUGINACTIVATOR_H #define MITKMATERIALEDITORPLUGINACTIVATOR_H #include namespace mitk { class MaterialEditorPluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // MaterialEditorPluginActivator } #endif // MITKMATERIALEDITORPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp index f2082f7be4..8dbdb06016 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "QmitkMeasurementView.h" #include "QmitkImageStatisticsView.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMeasurementView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkImageStatisticsView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org.mitk.gui.qt.measurementtoolbox, mitk::PluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.h index fbd2b87367..4a81939ee0 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.cpp index 0995ef5ffe..ab7038dc56 100644 --- a/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.cpp @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkMeshDecimationView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMeshDecimationView, context) //BERRY_REGISTER_EXTENSION_CLASS(QmitkHexVolumeMesherView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mbi_gui_qt_meshdecimation, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.h index a34be34be4..259bc9ffd6 100644 --- a/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.meshdecimation/src/internal/mitkPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include namespace mitk { class PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp index 1bcf462227..f4a3b930b5 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.cpp @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkMovieMakerPluginActivator.h" #include "QmitkMovieMaker.h" #include "QmitkScreenshotMaker.h" #include namespace mitk { void MovieMakerPluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMovieMaker, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkScreenshotMaker, context) } void MovieMakerPluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_moviemaker, mitk::MovieMakerPluginActivator) diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.h b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.h index 4bfa68d5cd..503382257a 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/mitkMovieMakerPluginActivator.h @@ -1,23 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKMOVIEMAKERPLUGINACTIVATOR_H #define MITKMOVIEMAKERPLUGINACTIVATOR_H #include namespace mitk { class MovieMakerPluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // MovieMakerPluginActivator } #endif // MITKMOVIEMAKERPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.cpp index a1701869e5..40bfc956f4 100644 --- a/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "QmitkPointSetInteractionView.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkPointSetInteractionView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_pointsetinteraction, mitk::PluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.h index 0549696692..40b59d188b 100644 --- a/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.pointsetinteraction/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.cpp index dc7cd0f797..b65d40b247 100644 --- a/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.cpp @@ -1,31 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "QmitkPythonConsoleView.h" #include "QmitkPythonVariableStack.h" #include "QmitkPythonCommandHistory.h" #include "QmitkPythonEditor.h" #include "QmitkPythonSnippets.h" #include "QmitkPythonPerspective.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonConsoleView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonVariableStack, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonCommandHistory, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonEditor, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonSnippets, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPythonPerspective, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_imagenavigator, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.h index c4b9e7885d..179331f8af 100644 --- a/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.python.console/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.cpp index 184831772f..ce74570c9d 100644 --- a/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.cpp @@ -1,26 +1,41 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "src/internal/QmitkDeformableRegistrationView.h" #include "src/internal/QmitkPointBasedRegistrationView.h" #include "src/internal/QmitkRigidRegistrationView.h" #include namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDeformableRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPointBasedRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkRigidRegistrationView, context) //Q_UNUSED(context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_registration, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.h index aabb457032..dc7ad4f70c 100644 --- a/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.registration/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp index d256fb92f5..7f60f53c2e 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp @@ -1,181 +1,196 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkAutocropAction.h" #include "mitkAutoCropImageFilter.h" #include "mitkImageCast.h" #include "mitkRenderingManager.h" #include "mitkProgressBar.h" #include //needed for qApp #include QmitkAutocropAction::QmitkAutocropAction() { } QmitkAutocropAction::~QmitkAutocropAction() { } void QmitkAutocropAction::Run( const QList &selectedNodes ) { foreach ( mitk::DataNode::Pointer node, selectedNodes ) { if (node) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNull()) return; mitk::ProgressBar::GetInstance()->AddStepsToDo(10); mitk::ProgressBar::GetInstance()->Progress(2); qApp->processEvents(); mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New(); cropFilter->SetInput( image ); cropFilter->SetBackgroundValue( 0 ); try { cropFilter->Update(); image = cropFilter->GetOutput(); if (image.IsNotNull()) { if (image->GetDimension() == 4) { MITK_INFO << "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; throw "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; unsigned int timesteps = image->GetDimension(3); for (unsigned int i = 0; i < timesteps; i++) { mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(image); imageTimeSelector->SetTimeNr(i); imageTimeSelector->UpdateLargestPossibleRegion(); // We split a long nested code line into separate calls for debugging: mitk::ImageSource::OutputImageType *_3dSlice = imageTimeSelector->GetOutput(); mitk::Image::Pointer _cropped3dSlice = this->IncreaseCroppedImageSize(_3dSlice); // +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ void *_data = _cropped3dSlice->GetData(); // // We write some stripes into the image if ((i & 1) == 0) { int depth = _cropped3dSlice->GetDimension(2); int height = _cropped3dSlice->GetDimension(1); int width = _cropped3dSlice->GetDimension(0); for (int z = 0; z < depth; ++z) for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) reinterpret_cast(_data)[(width * height * z) + (width * y) + x] = x & 1; // } image->SetVolume(_data, i); } node->SetData( image ); // bug fix 3145 } else { node->SetData( this->IncreaseCroppedImageSize(image) ); // bug fix 3145 } // Reinit node mitk::RenderingManager::GetInstance()->InitializeViews( node->GetData()->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } catch(...) { MITK_ERROR << "Cropping image failed..."; } mitk::ProgressBar::GetInstance()->Progress(8); } else { MITK_INFO << " a NULL node selected"; } } } mitk::Image::Pointer QmitkAutocropAction::IncreaseCroppedImageSize( mitk::Image::Pointer image ) { typedef itk::Image< short, 3 > ImageType; typedef itk::Image< unsigned char, 3 > PADOutputImageType; ImageType::Pointer itkTransformImage = ImageType::New(); mitk::CastToItkImage( image, itkTransformImage ); typedef itk::ConstantPadImageFilter< ImageType, PADOutputImageType > PadFilterType; PadFilterType::Pointer padFilter = PadFilterType::New(); unsigned long upperPad[3]; unsigned long lowerPad[3]; int borderLiner = 3; mitk::Point3D mitkOriginPoint; double origin[3]; origin[0]=0; origin[1]=0; origin[2]=0; itkTransformImage->SetOrigin(origin); lowerPad[0]=borderLiner; lowerPad[1]=borderLiner; lowerPad[2]=borderLiner; upperPad[0]=borderLiner; upperPad[1]=borderLiner; upperPad[2]=borderLiner; padFilter->SetInput(itkTransformImage); padFilter->SetConstant(0); padFilter->SetPadUpperBound(upperPad); padFilter->SetPadLowerBound(lowerPad); padFilter->UpdateLargestPossibleRegion(); mitk::Image::Pointer paddedImage = mitk::Image::New(); paddedImage->InitializeByItk(padFilter->GetOutput()); mitk::CastToMitkImage(padFilter->GetOutput(), paddedImage); //calculate translation according to padding to get the new origin mitk::Point3D paddedOrigin = image->GetGeometry()->GetOrigin(); mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); paddedOrigin[0] -= (borderLiner)*spacing[0]; paddedOrigin[1] -= (borderLiner)*spacing[1]; paddedOrigin[2] -= (borderLiner)*spacing[2]; paddedImage->GetGeometry()->SetOrigin( paddedOrigin ); return paddedImage; } void QmitkAutocropAction::SetSmoothed(bool /*smoothed*/) { //not needed } void QmitkAutocropAction::SetDecimated(bool /*decimated*/) { //not needed } void QmitkAutocropAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) { //not needed } void QmitkAutocropAction::SetFunctionality(berry::QtViewPart* /*functionality*/) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h index 54e8556be9..3003a36e6d 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h @@ -1,41 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITK_AUTOCROPACTION_H #define QMITK_AUTOCROPACTION_H #include "mitkIContextMenuAction.h" #include "org_mitk_gui_qt_segmentation_Export.h" #include "vector" #include "mitkDataNode.h" #include "mitkImage.h" class QmitkStdMultiWidget; class MITK_QT_SEGMENTATION QmitkAutocropAction : public QObject, public mitk::IContextMenuAction { Q_OBJECT Q_INTERFACES(mitk::IContextMenuAction) public: QmitkAutocropAction(); virtual ~QmitkAutocropAction(); //interface methods void Run( const QList& selectedNodes ); void SetDataStorage(mitk::DataStorage* dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart* functionality); protected: mitk::Image::Pointer IncreaseCroppedImageSize( mitk::Image::Pointer image ); private: typedef QList NodeList; }; #endif // QMITK_AUTOCROPACTION_H diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp index a467d1bd2f..d2d5bde8a4 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp @@ -1,151 +1,166 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkCreatePolygonModelAction.h" // MITK #include #include #include #include #include #include #include // Blueberry #include #include #include using namespace berry; using namespace mitk; using namespace std; QmitkCreatePolygonModelAction::QmitkCreatePolygonModelAction() { } QmitkCreatePolygonModelAction::~QmitkCreatePolygonModelAction() { } void QmitkCreatePolygonModelAction::Run(const QList &selectedNodes) { DataNode::Pointer selectedNode = selectedNodes[0]; Image::Pointer image = dynamic_cast(selectedNode->GetData()); if (image.IsNull()) return; try { if (!m_IsSmoothed) { ShowSegmentationAsSurface::Pointer surfaceFilter = ShowSegmentationAsSurface::New(); itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); surfaceFilter->AddObserver(ResultAvailable(), successCommand); itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); surfaceFilter->AddObserver(ProcessingError(), errorCommand); surfaceFilter->SetDataStorage(*m_DataStorage); surfaceFilter->SetPointerParameter("Input", image); surfaceFilter->SetPointerParameter("Group node", selectedNode); surfaceFilter->SetParameter("Show result", true); surfaceFilter->SetParameter("Sync visibility", false); surfaceFilter->SetParameter("Smooth", false); surfaceFilter->SetParameter("Apply median", false); surfaceFilter->SetParameter("Median kernel size", 3u); surfaceFilter->SetParameter("Gaussian SD", 1.5f); surfaceFilter->SetParameter("Decimate mesh", m_IsDecimated); surfaceFilter->SetParameter("Decimation rate", 0.8f); StatusBar::GetInstance()->DisplayText("Surface creation started in background..."); surfaceFilter->StartAlgorithm(); } else { ShowSegmentationAsSmoothedSurface::Pointer surfaceFilter = ShowSegmentationAsSmoothedSurface::New(); itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand); itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand); surfaceFilter->SetDataStorage(*m_DataStorage); surfaceFilter->SetPointerParameter("Input", image); surfaceFilter->SetPointerParameter("Group node", selectedNode); berry::IWorkbenchPart::Pointer activePart = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->GetActivePart(); mitk::IRenderWindowPart* renderPart = dynamic_cast(activePart.GetPointer()); mitk::SliceNavigationController* timeNavController = 0; if (renderPart != 0) { timeNavController = renderPart->GetRenderingManager()->GetTimeNavigationController(); } int timeNr = timeNavController != 0 ? timeNavController->GetTime()->GetPos() : 0; surfaceFilter->SetParameter("TimeNr", timeNr); IPreferencesService::Pointer prefService = Platform::GetServiceRegistry().GetServiceById(IPreferencesService::ID); IPreferences::Pointer segPref = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); bool smoothingHint = segPref->GetBool("smoothing hint", true); float smoothing = (float)segPref->GetDouble("smoothing value", 1.0); float decimation = (float)segPref->GetDouble("decimation rate", 0.5); float closing = (float)segPref->GetDouble("closing ratio", 0.0); if (smoothingHint) { smoothing = 0.0; Vector3D spacing = image->GetGeometry()->GetSpacing(); for (Vector3D::Iterator iter = spacing.Begin(); iter != spacing.End(); ++iter) smoothing = max(smoothing, *iter); } surfaceFilter->SetParameter("Smoothing", smoothing); surfaceFilter->SetParameter("Decimation", decimation); surfaceFilter->SetParameter("Closing", closing); ProgressBar::GetInstance()->AddStepsToDo(8); StatusBar::GetInstance()->DisplayText("Smoothed surface creation started in background..."); surfaceFilter->StartAlgorithm(); } } catch(...) { MITK_ERROR << "Surface creation failed!"; } } void QmitkCreatePolygonModelAction::OnSurfaceCalculationDone() { StatusBar::GetInstance()->Clear(); } void QmitkCreatePolygonModelAction::SetDataStorage(DataStorage *dataStorage) { m_DataStorage = dataStorage; } void QmitkCreatePolygonModelAction::SetSmoothed(bool smoothed) { m_IsSmoothed = smoothed; } void QmitkCreatePolygonModelAction::SetDecimated(bool decimated) { m_IsDecimated = decimated; } void QmitkCreatePolygonModelAction::SetFunctionality(QtViewPart *) { } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h index cea5805fa9..e5e4031d56 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h @@ -1,42 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKCREATEPOLYGONMODELACTION_H #define QMITKCREATEPOLYGONMODELACTION_H #include // Parent classes #include #include // Data members #include class QmitkStdMultiWidget; class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction : public QObject, public mitk::IContextMenuAction { Q_OBJECT Q_INTERFACES(mitk::IContextMenuAction) public: QmitkCreatePolygonModelAction(); ~QmitkCreatePolygonModelAction(); // IContextMenuAction void Run(const QList &selectedNodes); void SetDataStorage(mitk::DataStorage *dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart *functionality); void OnSurfaceCalculationDone(); private: QmitkCreatePolygonModelAction(const QmitkCreatePolygonModelAction &); QmitkCreatePolygonModelAction & operator=(const QmitkCreatePolygonModelAction &); mitk::DataStorage::Pointer m_DataStorage; bool m_IsSmoothed; bool m_IsDecimated; }; #endif diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp index f530ac6789..ef850ce1f0 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp @@ -1,1229 +1,1239 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDataNodeObject.h" #include "mitkProperties.h" #include "mitkSegTool2D.h" #include "mitkGlobalInteraction.h" #include "QmitkStdMultiWidget.h" #include "QmitkNewSegmentationDialog.h" #include #include #include "QmitkSegmentationView.h" #include "QmitkSegmentationPostProcessing.h" #include "QmitkSegmentationOrganNamesHandling.cpp" #include #include //For Segmentation in rotated slices //TODO clean up includes #include "mitkVtkResliceInterpolationProperty.h" #include "mitkPlanarCircle.h" #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" #include "mitkSegmentationObjectFactory.h" const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation"; // public methods QmitkSegmentationView::QmitkSegmentationView() :m_Parent(NULL) ,m_Controls(NULL) ,m_MultiWidget(NULL) ,m_RenderingManagerObserverTag(0) { RegisterSegmentationObjectFactory(); } QmitkSegmentationView::~QmitkSegmentationView() { // delete m_PostProcessing; delete m_Controls; } void QmitkSegmentationView::NewNodesGenerated() { // ForceDisplayPreferencesUponAllImages(); } void QmitkSegmentationView::NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType* nodes) { if (!nodes) return; mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); if (!toolManager) return; for (mitk::ToolManager::DataVectorType::iterator iter = nodes->begin(); iter != nodes->end(); ++iter) { this->FireNodeSelected( *iter ); // only last iteration meaningful, multiple generated objects are not taken into account here } } void QmitkSegmentationView::Activated() { // should be moved to ::BecomesVisible() or similar if( m_Controls ) { m_Controls->m_ManualToolSelectionBox->setEnabled( true ); m_Controls->m_OrganToolSelectionBox->setEnabled( true ); m_Controls->m_LesionToolSelectionBox->setEnabled( true ); m_Controls->m_SlicesInterpolator->Enable3DInterpolation( m_Controls->widgetStack->currentWidget() == m_Controls->pageManual ); //TODO Remove Observer itk::ReceptorMemberCommand::Pointer command1 = itk::ReceptorMemberCommand::New(); command1->SetCallbackFunction( this, &QmitkSegmentationView::RenderingManagerReinitialized ); m_RenderingManagerObserverTag = mitk::RenderingManager::GetInstance()->AddObserver( mitk::RenderingManagerViewsInitializedEvent(), command1 ); //Adding observers for node visibility to existing segmentations mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isSegmentation = mitk::NodePredicateAnd::New( isImage, isBinary ); mitk::DataStorage::SetOfObjects::ConstPointer segmentations = this->GetDefaultDataStorage()->GetSubset( isSegmentation ); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = segmentations->begin(); iter != segmentations->end(); ++iter) { mitk::DataNode* node = *iter; itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged); m_WorkingDataObserverTags.insert( std::pair( node, node->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) ); } if(segmentations->Size() > 0) { FireNodeSelected(segmentations->ElementAt(0)); segmentations->ElementAt(0)->GetProperty("visible")->Modified(); } } } void QmitkSegmentationView::Deactivated() { if( m_Controls ) { mitk::RenderingManager::GetInstance()->RemoveObserver( m_RenderingManagerObserverTag ); m_Controls->m_ManualToolSelectionBox->setEnabled( false ); //deactivate all tools m_Controls->m_ManualToolSelectionBox->GetToolManager()->ActivateTool(-1); m_Controls->m_OrganToolSelectionBox->setEnabled( false ); m_Controls->m_LesionToolSelectionBox->setEnabled( false ); m_Controls->m_SlicesInterpolator->EnableInterpolation( false ); //Removing all observers for ( NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter ) { (*dataIter).first->GetProperty("visible")->RemoveObserver( (*dataIter).second ); } m_WorkingDataObserverTags.clear(); + if (m_MultiWidget) + { + mitk::SlicesCoordinator *coordinator = m_MultiWidget->GetSlicesRotator(); + + if (coordinator) + coordinator->RemoveObserver(m_SlicesRotationObserverTag1); + + coordinator = m_MultiWidget->GetSlicesSwiveller(); + + if (coordinator) + coordinator->RemoveObserver(m_SlicesRotationObserverTag2); + + } + // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTL plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); //mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); service->RemoveAllPlanePositions(); } } void QmitkSegmentationView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget ) { SetMultiWidget(&stdMultiWidget); } void QmitkSegmentationView::StdMultiWidgetNotAvailable() { SetMultiWidget(NULL); } void QmitkSegmentationView::StdMultiWidgetClosed( QmitkStdMultiWidget& /*stdMultiWidget*/ ) { SetMultiWidget(NULL); } void QmitkSegmentationView::SetMultiWidget(QmitkStdMultiWidget* multiWidget) { if (m_MultiWidget) { mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); if (coordinator) { coordinator->RemoveObserver( m_SlicesRotationObserverTag1 ); } coordinator = m_MultiWidget->GetSlicesSwiveller(); if (coordinator) { coordinator->RemoveObserver( m_SlicesRotationObserverTag2 ); } } // save the current multiwidget as the working widget m_MultiWidget = multiWidget; //TODO Remove Observers if (m_MultiWidget) { mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSegmentationView::SliceRotation ); m_SlicesRotationObserverTag1 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } coordinator = m_MultiWidget->GetSlicesSwiveller(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSegmentationView::SliceRotation ); m_SlicesRotationObserverTag2 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } } //TODO End Remove Observers if (m_Parent) { m_Parent->setEnabled(m_MultiWidget); } // tell the interpolation about toolmanager and multiwidget (and data storage) if (m_Controls && m_MultiWidget) { mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); m_Controls->m_SlicesInterpolator->SetDataStorage( *(this->GetDefaultDataStorage())); m_Controls->m_SlicesInterpolator->Initialize( toolManager, m_MultiWidget ); } } void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences*) { ForceDisplayPreferencesUponAllImages(); } //TODO remove function void QmitkSegmentationView::RenderingManagerReinitialized(const itk::EventObject&) { CheckImageAlignment(); } //TODO remove function void QmitkSegmentationView::SliceRotation(const itk::EventObject&) { CheckImageAlignment(); } // protected slots void QmitkSegmentationView::CreateNewSegmentation() { mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull()) { if (image->GetDimension()>1) { // ask about the name and organ type of the new segmentation QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( m_Parent ); // needs a QWidget as parent, "this" is not QWidget QString storedList = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") ); QStringList organColors; if (storedList.isEmpty()) { organColors = GetDefaultOrganColorString(); } else { /* a couple of examples of how organ names are stored: a simple item is built up like 'name#AABBCC' where #AABBCC is the hexadecimal notation of a color as known from HTML items are stored separated by ';' this makes it necessary to escape occurrences of ';' in name. otherwise the string "hugo;ypsilon#AABBCC;eugen#AABBCC" could not be parsed as two organs but we would get "hugo" and "ypsilon#AABBCC" and "eugen#AABBCC" so the organ name "hugo;ypsilon" is stored as "hugo\;ypsilon" and must be unescaped after loading the following lines could be one split with Perl's negative lookbehind */ // recover string list from BlueBerry view's preferences QString storedString = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") ); MITK_DEBUG << "storedString: " << storedString.toStdString(); // match a string consisting of any number of repetitions of either "anything but ;" or "\;". This matches everything until the next unescaped ';' QRegExp onePart("(?:[^;]|\\\\;)*"); MITK_DEBUG << "matching " << onePart.pattern().toStdString(); int count = 0; int pos = 0; while( (pos = onePart.indexIn( storedString, pos )) != -1 ) { ++count; int length = onePart.matchedLength(); if (length == 0) break; QString matchedString = storedString.mid(pos, length); MITK_DEBUG << " Captured length " << length << ": " << matchedString.toStdString(); pos += length + 1; // skip separating ';' // unescape possible occurrences of '\;' in the string matchedString.replace("\\;", ";"); // add matched string part to output list organColors << matchedString; } MITK_DEBUG << "Captured " << count << " organ name/colors"; } dialog->SetSuggestionList( organColors ); int dialogReturnValue = dialog->exec(); if ( dialogReturnValue == QDialog::Rejected ) return; // user clicked cancel or pressed Esc or something similar // ask the user about an organ type and name, add this information to the image's (!) propertylist // create a new image of the same dimensions and smallest possible pixel type mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); mitk::Tool* firstTool = toolManager->GetToolById(0); if (firstTool) { try { mitk::DataNode::Pointer emptySegmentation = firstTool->CreateEmptySegmentationNode( image, dialog->GetSegmentationName().toStdString(), dialog->GetColor() ); //Here we change the reslice interpolation mode for a segmentation, so that contours in rotated slice can be shown correctly emptySegmentation->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_LINEAR) ); // initialize showVolume to false to prevent recalculating the volume while working on the segmentation emptySegmentation->SetProperty( "showVolume", mitk::BoolProperty::New( false ) ); if (!emptySegmentation) return; // could be aborted by user UpdateOrganList( organColors, dialog->GetSegmentationName(), dialog->GetColor() ); /* escape ';' here (replace by '\;'), see longer comment above */ std::string stringForStorage = organColors.replaceInStrings(";","\\;").join(";").toStdString(); MITK_DEBUG << "Will store: " << stringForStorage; this->GetPreferences()->PutByteArray("Organ-Color-List", stringForStorage ); this->GetPreferences()->Flush(); if(m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0)) { m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0)->SetSelected(false); } emptySegmentation->SetSelected(true); this->GetDefaultDataStorage()->Add( emptySegmentation, node ); // add as a child, because the segmentation "derives" from the original this->FireNodeSelected( emptySegmentation ); this->OnSelectionChanged( emptySegmentation ); this->SetToolManagerSelection(node, emptySegmentation); } catch (std::bad_alloc) { QMessageBox::warning(NULL,"Create new segmentation","Could not allocate memory for new segmentation"); } } } else { QMessageBox::information(NULL,"Segmentation","Segmentation is currently not supported for 2D images"); } } } else { MITK_ERROR << "'Create new segmentation' button should never be clickable unless a patient image is selected..."; } } void QmitkSegmentationView::OnWorkingNodeVisibilityChanged(/*const itk::Object* caller, const itk::EventObject& e*/) { if (!m_Parent || !m_Parent->isVisible()) return; // The new selection behaviour is: // // When clicking on the checkbox of a segmentation the node will e selected and its reference node either // The previous selected segmentation (if there is one) will be deselected. Additionally a reinit on the // selected segmenation will be performed. // If more than one segmentation is selected the tools will be disabled. if (!m_Controls) return; // might happen on initialization (preferences loaded) mitk::DataNode::Pointer referenceDataNew = mitk::DataNode::New(); mitk::DataNode::Pointer workingData; bool workingNodeIsVisible (true); unsigned int numberOfSelectedSegmentations (0); // iterate all images mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDefaultDataStorage()->GetSubset( isImage ); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { mitk::DataNode* node = *iter; // apply display preferences ApplyDisplayOptions(node); bool isSegmentation(false); node->GetBoolProperty("binary", isSegmentation); if (node->IsSelected() && isSegmentation) { workingNodeIsVisible = node->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); if (!workingNodeIsVisible) return; numberOfSelectedSegmentations++; workingData = node; if (this->GetDefaultDataStorage()->GetSources(node)->Size() != 0) { referenceDataNew = this->GetDefaultDataStorage()->GetSources(node)->ElementAt(0); } bool isBinary(false); //Find topmost source or first source which is no binary image while (referenceDataNew && this->GetDefaultDataStorage()->GetSources(referenceDataNew)->Size() != 0) { referenceDataNew = this->GetDefaultDataStorage()->GetSources(referenceDataNew)->ElementAt(0); referenceDataNew->GetBoolProperty("binary",isBinary); if (!isBinary) break; } if (workingNodeIsVisible && referenceDataNew) { //Since the binary property of a segmentation can be set to false and afterwards you can create a new segmentation out of it //->could lead to a deadloop NodeTagMapType::iterator searchIter = m_WorkingDataObserverTags.find( referenceDataNew ); if ( searchIter != m_WorkingDataObserverTags.end()) { referenceDataNew->GetProperty("visible")->RemoveObserver( (*searchIter).second ); } referenceDataNew->SetVisibility(true); } //set comboBox to reference image disconnect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->refImageSelector->setCurrentIndex( m_Controls->refImageSelector->Find(referenceDataNew) ); connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); continue; } if (workingData.IsNull() || (workingNodeIsVisible && node != referenceDataNew)) { node->SetVisibility((false)); } } if(numberOfSelectedSegmentations == 1) SetToolManagerSelection(referenceDataNew, workingData); mitk::DataStorage::SetOfObjects::Pointer temp = mitk::DataStorage::SetOfObjects::New(); temp->InsertElement(0,workingData); mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(temp); // initialize the views to the bounding geometry /*mitk::RenderingManager::GetInstance()->InitializeViews(bounds); mitk::RenderingManager::GetInstance()->RequestUpdateAll();*/ } void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node) { bool isSeg(false); bool isHelperObject(false); node->GetBoolProperty("helper object", isHelperObject); node->GetBoolProperty("binary", isSeg); if(isSeg && !isHelperObject) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(node, mitk::NodePredicateProperty::New("isContourMarker" , mitk::BoolProperty::New(true))); // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTL plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); //mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t+1).c_str())-1; service->RemovePlanePosition(id); this->GetDataStorage()->Remove(it->Value()); } mitk::DataNode* tempNode = const_cast(node); node->GetProperty("visible")->RemoveObserver( m_WorkingDataObserverTags[tempNode] ); m_WorkingDataObserverTags.erase(tempNode); this->SetToolManagerSelection(NULL, NULL); } } void QmitkSegmentationView::CreateSegmentationFromSurface() { mitk::DataNode::Pointer surfaceNode = m_Controls->MaskSurfaces->GetSelectedNode(); mitk::Surface::Pointer surface(0); if(surfaceNode.IsNotNull()) surface = dynamic_cast ( surfaceNode->GetData() ); if(surface.IsNull()) { this->HandleException( "No surface selected.", m_Parent, true); return; } mitk::DataNode::Pointer imageNode = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); mitk::Image::Pointer image(0); if (imageNode.IsNotNull()) image = dynamic_cast( imageNode->GetData() ); if(image.IsNull()) { this->HandleException( "No image selected.", m_Parent, true); return; } mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(surface); s2iFilter->SetImage(image); s2iFilter->Update(); mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); std::string nameOfResultImage = imageNode->GetName(); nameOfResultImage.append(surfaceNode->GetName()); resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); resultNode->SetProperty("binary", mitk::BoolProperty::New(true) ); resultNode->SetData( s2iFilter->GetOutput() ); this->GetDataStorage()->Add(resultNode, imageNode); } void QmitkSegmentationView::ManualToolSelected(int id) { // disable crosshair movement when a manual drawing tool is active (otherwise too much visual noise) if (m_MultiWidget) { if (id >= 0) { m_MultiWidget->DisableNavigationControllerEventListening(); } else { m_MultiWidget->EnableNavigationControllerEventListening(); } } } void QmitkSegmentationView::ToolboxStackPageChanged(int id) { // interpolation only with manual tools visible m_Controls->m_SlicesInterpolator->EnableInterpolation( id == 0 ); if( id == 0 ) { mitk::DataNode::Pointer workingData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0); if( workingData.IsNotNull() ) { m_Controls->lblSegmentation->setText( workingData->GetName().c_str() ); m_Controls->lblSegImage->show(); m_Controls->lblSegmentation->show(); } } else { m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } // this is just a workaround, should be removed when all tools support 3D+t if (id==2) // lesions { mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull()) { if (image->GetDimension()>3) { m_Controls->widgetStack->setCurrentIndex(0); QMessageBox::information(NULL,"Segmentation","Lesion segmentation is currently not supported for 4D images"); } } } } } // protected void QmitkSegmentationView::OnComboBoxSelectionChanged( const mitk::DataNode* node ) { mitk::DataNode* selectedNode = const_cast(node); if( selectedNode != NULL ) { m_Controls->refImageSelector->show(); m_Controls->lblReferenceImageSelectionWarning->hide(); bool isBinary(false); selectedNode->GetBoolProperty("binary", isBinary); if ( isBinary ) { FireNodeSelected(selectedNode); selectedNode->SetVisibility(true); } else if (node != m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0)) { if (m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0)) m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0)->SetVisibility(false); if (m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0)) { m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0)->SetVisibility(false); } FireNodeSelected(selectedNode); selectedNode->SetVisibility(true); SetToolManagerSelection(selectedNode, NULL); } } else { m_Controls->refImageSelector->hide(); m_Controls->lblReferenceImageSelectionWarning->show(); } } void QmitkSegmentationView::OnShowMarkerNodes (bool state) { mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetTools().size(); for(unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetToolById(i)); if (manualSegmentationTool) { if(state == true) { manualSegmentationTool->SetShowMarkerNodes( true ); } else { manualSegmentationTool->SetShowMarkerNodes( false ); } } } } void QmitkSegmentationView::On3DInterpolationEnabled (bool state) { mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetTools().size(); for(unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetToolById(i)); if (manualSegmentationTool) { manualSegmentationTool->Enable3DInterpolation( state ); } } } void QmitkSegmentationView::OnSelectionChanged(mitk::DataNode* node) { std::vector nodes; nodes.push_back( node ); this->OnSelectionChanged( nodes ); } void QmitkSegmentationView::OnSurfaceSelectionChanged() { // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull())) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); } void QmitkSegmentationView::OnSelectionChanged(std::vector nodes) { // if the selected node is a contourmarker if ( !nodes.empty() ) { std::string markerName = "Position"; unsigned int numberOfNodes = nodes.size(); std::string nodeName = nodes.at( 0 )->GetName(); if ( ( numberOfNodes == 1 ) && ( nodeName.find( markerName ) == 0) ) { this->OnContourMarkerSelected( nodes.at( 0 ) ); } } // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull())) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); if (!m_Parent || !m_Parent->isVisible()) return; // reaction to BlueBerry selection events // this method will try to figure out if a relevant segmentation and its corresponding original image were selected // a warning is issued if the selection is invalid // appropriate reactions are triggered otherwise mitk::DataNode::Pointer referenceData = FindFirstRegularImage( nodes ); //m_Controls->refImageSelector->GetSelectedNode(); //FindFirstRegularImage( nodes ); mitk::DataNode::Pointer workingData = FindFirstSegmentation( nodes ); if(referenceData.IsNull() && workingData.IsNull()) return; bool invalidSelection( !nodes.empty() && ( nodes.size() > 2 || // maximum 2 selected nodes (nodes.size() == 2 && (workingData.IsNull() || referenceData.IsNull()) ) || // with two nodes, one must be the original image, one the segmentation ( workingData.GetPointer() == referenceData.GetPointer() ) //one node is selected as reference and working image // one item is always ok (might be working or reference or nothing ) ); if (invalidSelection) { // TODO visible warning when two images are selected MITK_ERROR << "WARNING: No image, too many (>2) or two equal images were selected."; workingData = NULL; if( m_Controls->refImageSelector->GetSelectedNode().IsNull() ) referenceData = NULL; } if ( workingData.IsNotNull() && referenceData.IsNull() ) { // find the DataStorage parent of workingData // try to find a "normal image" parent, select this as reference image mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinary = mitk::NodePredicateNot::New( isBinary ); mitk::NodePredicateAnd::Pointer isNormalImage = mitk::NodePredicateAnd::New( isImage, isNotBinary ); mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( workingData, isNormalImage ); if (possibleParents->size() > 0) { if (possibleParents->size() > 1) { // TODO visible warning for this rare case MITK_ERROR << "Selected binary image has multiple parents. Using arbitrary first one for segmentation."; } referenceData = (*possibleParents)[0]; } NodeTagMapType::iterator searchIter = m_WorkingDataObserverTags.find( workingData ); if ( searchIter == m_WorkingDataObserverTags.end() ) { //MITK_INFO<<"Creating new observer"; itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged); m_WorkingDataObserverTags.insert( std::pair( workingData, workingData->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) ); workingData->GetProperty("visible")->Modified(); return; } if(workingData->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")))) { //set comboBox to reference image disconnect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->refImageSelector->setCurrentIndex( m_Controls->refImageSelector->Find(workingData) ); connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull()) || (!referenceData)) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); SetToolManagerSelection(referenceData, workingData); FireNodeSelected(workingData); } else { SetToolManagerSelection(NULL, NULL); FireNodeSelected(workingData); } } else { //set comboBox to reference image disconnect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->refImageSelector->setCurrentIndex( m_Controls->refImageSelector->Find(referenceData) ); connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull()) || (!referenceData)) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); SetToolManagerSelection(referenceData, workingData); FireNodeSelected(referenceData); } } void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode *node) { //TODO renderWindow anders bestimmen, siehe CheckAlignment QmitkRenderWindow* selectedRenderWindow = 0; QmitkRenderWindow* RenderWindow1 = this->GetActiveStdMultiWidget()->GetRenderWindow1(); QmitkRenderWindow* RenderWindow2 = this->GetActiveStdMultiWidget()->GetRenderWindow2(); QmitkRenderWindow* RenderWindow3 = this->GetActiveStdMultiWidget()->GetRenderWindow3(); QmitkRenderWindow* RenderWindow4 = this->GetActiveStdMultiWidget()->GetRenderWindow4(); bool PlanarFigureInitializedWindow = false; // find initialized renderwindow if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer())) { selectedRenderWindow = RenderWindow1; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer())) { selectedRenderWindow = RenderWindow2; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow3->GetRenderer())) { selectedRenderWindow = RenderWindow3; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer())) { selectedRenderWindow = RenderWindow4; } // make node visible if (selectedRenderWindow) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t+1).c_str())-1; // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTL plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); //mitk::ServiceReference serviceRef = mitk::GetModuleContext()->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id)); selectedRenderWindow->GetRenderer()->GetDisplayGeometry()->Fit(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } mitk::DataNode::Pointer QmitkSegmentationView::FindFirstRegularImage( std::vector nodes ) { if (nodes.empty()) return NULL; for(unsigned int i = 0; i < nodes.size(); ++i) { //mitk::DataNode::Pointer node = i.value() bool isImage(false); if (nodes.at(i)->GetData()) { isImage = dynamic_cast(nodes.at(i)->GetData()) != NULL; } // make sure this is not a binary image bool isSegmentation(false); nodes.at(i)->GetBoolProperty("binary", isSegmentation); // return first proper mitk::Image if (isImage && !isSegmentation) return nodes.at(i); } return NULL; } mitk::DataNode::Pointer QmitkSegmentationView::FindFirstSegmentation( std::vector nodes ) { if (nodes.empty()) return NULL; for(unsigned int i = 0; i < nodes.size(); ++i) { bool isImage(false); if (nodes.at(i)->GetData()) { isImage = dynamic_cast(nodes.at(i)->GetData()) != NULL; } bool isSegmentation(false); nodes.at(i)->GetBoolProperty("binary", isSegmentation); // return first proper binary mitk::Image if (isImage && isSegmentation) { return nodes.at(i); } } return NULL; } void QmitkSegmentationView::SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData) { // called as a result of new BlueBerry selections // tells the ToolManager for manual segmentation about new selections // updates GUI information about what the user should select mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); toolManager->SetReferenceData(const_cast(referenceData)); toolManager->SetWorkingData( const_cast(workingData)); // check original image m_Controls->btnNewSegmentation->setEnabled(referenceData != NULL); if (referenceData) { m_Controls->lblReferenceImageSelectionWarning->hide(); } else { m_Controls->lblReferenceImageSelectionWarning->show(); m_Controls->lblWorkingImageSelectionWarning->hide(); m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } //TODO remove statement // check, wheter reference image is aligned like render windows. Otherwise display a visible warning (because 2D tools will probably not work) CheckImageAlignment(); // check segmentation if (referenceData) { if (!workingData) { m_Controls->lblWorkingImageSelectionWarning->show(); if( m_Controls->widgetStack->currentIndex() == 0 ) { m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } } else { m_Controls->lblWorkingImageSelectionWarning->hide(); this->FireNodeSelected(const_cast(workingData)); if( m_Controls->widgetStack->currentIndex() == 0 ) { m_Controls->lblSegmentation->setText( workingData->GetName().c_str() ); m_Controls->lblSegmentation->show(); m_Controls->lblSegImage->show(); } } } } //TODO remove function void QmitkSegmentationView::CheckImageAlignment() { bool wrongAlignment(true); mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull() && m_MultiWidget) { wrongAlignment = !( IsRenderWindowAligned(m_MultiWidget->GetRenderWindow1(), image ) && IsRenderWindowAligned(m_MultiWidget->GetRenderWindow2(), image ) && IsRenderWindowAligned(m_MultiWidget->GetRenderWindow3(), image ) ); } - - if (wrongAlignment) - { - m_Controls->lblAlignmentWarning->show(); - } } + m_Controls->lblAlignmentWarning->setVisible(wrongAlignment); } //TODO remove function bool QmitkSegmentationView::IsRenderWindowAligned(QmitkRenderWindow* renderWindow, mitk::Image* image) { if (!renderWindow) return false; // for all 2D renderwindows of m_MultiWidget check alignment mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( renderWindow->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; int affectedDimension(-1); int affectedSlice(-1); return mitk::SegTool2D::DetermineAffectedImageSlice( image, displayPlane, affectedDimension, affectedSlice ); } //TODO remove function void QmitkSegmentationView::ForceDisplayPreferencesUponAllImages() { if (!m_Parent || !m_Parent->isVisible()) return; // check all images and segmentations in DataStorage: // (items in brackets are implicitly done by previous steps) // 1. // if a reference image is selected, // show the reference image // and hide all other images (orignal and segmentation), // (and hide all segmentations of the other original images) // and show all the reference's segmentations // if no reference image is selected, do do nothing // // 2. // if a segmentation is selected, // show it // (and hide all all its siblings (childs of the same parent, incl, NULL parent)) // if no segmentation is selected, do nothing if (!m_Controls) return; // might happen on initialization (preferences loaded) mitk::DataNode::Pointer referenceData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); mitk::DataNode::Pointer workingData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0); // 1. if (referenceData.IsNotNull()) { // iterate all images mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDefaultDataStorage()->GetSubset( isImage ); //mitk::DataStorage::SetOfObjects::ConstPointer allSegmentationChilds = this->GetDefaultDataStorage()->GetDerivations(referenceData, isImage ); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { mitk::DataNode* node = *iter; // apply display preferences ApplyDisplayOptions(node); // set visibility if(!node->IsSelected() || (node->IsSelected() && !node->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))))) node->SetVisibility((node == referenceData) || node->IsSelected() ); } } // 2. //if (workingData.IsNotNull() && !workingData->IsSelected()) //{ // workingData->SetVisibility(true); //} mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node) { if (!node) return; bool isBinary(false); node->GetPropertyValue("binary", isBinary); if (isBinary) { node->SetProperty( "outline binary", mitk::BoolProperty::New( this->GetPreferences()->GetBool("draw outline", true)) ); node->SetProperty( "outline width", mitk::FloatProperty::New( 2.0 ) ); node->SetProperty( "opacity", mitk::FloatProperty::New( this->GetPreferences()->GetBool("draw outline", true) ? 1.0 : 0.3 ) ); node->SetProperty( "volumerendering", mitk::BoolProperty::New( this->GetPreferences()->GetBool("volume rendering", false) ) ); } } void QmitkSegmentationView::CreateQtPartControl(QWidget* parent) { // setup the basic GUI of this view m_Parent = parent; m_Controls = new Ui::QmitkSegmentationControls; m_Controls->setupUi(parent); m_Controls->lblWorkingImageSelectionWarning->hide(); m_Controls->lblAlignmentWarning->hide(); m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); m_Controls->refImageSelector->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->refImageSelector->SetPredicate(mitk::NodePredicateDataType::New("Image")); if( m_Controls->refImageSelector->GetSelectedNode().IsNotNull() ) m_Controls->lblReferenceImageSelectionWarning->hide(); else m_Controls->refImageSelector->hide(); mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); toolManager->SetDataStorage( *(this->GetDefaultDataStorage()) ); assert ( toolManager ); // all part of open source MITK m_Controls->m_ManualToolSelectionBox->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer ); m_Controls->m_ManualToolSelectionBox->SetDisplayedToolGroups("Add Subtract Paint Wipe 'Region Growing' Correction Fill Erase"); m_Controls->m_ManualToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingData ); // available only in the 3M application if ( !m_Controls->m_OrganToolSelectionBox->children().count() ) { m_Controls->widgetStack->setItemEnabled( 1, false ); } m_Controls->m_OrganToolSelectionBox->SetToolManager( *toolManager ); m_Controls->m_OrganToolSelectionBox->SetToolGUIArea( m_Controls->m_OrganToolGUIContainer ); m_Controls->m_OrganToolSelectionBox->SetDisplayedToolGroups("'Hippocampus left' 'Hippocampus right' 'Lung left' 'Lung right' 'Liver' 'Heart LV' 'Endocard LV' 'Epicard LV' 'Prostate'"); m_Controls->m_OrganToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceData ); // available only in the 3M application if ( !m_Controls->m_LesionToolSelectionBox->children().count() ) { m_Controls->widgetStack->setItemEnabled( 2, false ); } m_Controls->m_LesionToolSelectionBox->SetToolManager( *toolManager ); m_Controls->m_LesionToolSelectionBox->SetToolGUIArea( m_Controls->m_LesionToolGUIContainer ); m_Controls->m_LesionToolSelectionBox->SetDisplayedToolGroups("'Lymph Node'"); m_Controls->m_LesionToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceData ); toolManager->NewNodesGenerated += mitk::MessageDelegate( this, &QmitkSegmentationView::NewNodesGenerated ); // update the list of segmentations toolManager->NewNodeObjectsGenerated += mitk::MessageDelegate1( this, &QmitkSegmentationView::NewNodeObjectsGenerated ); // update the list of segmentations // create signal/slot connections connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); connect( m_Controls->btnNewSegmentation, SIGNAL(clicked()), this, SLOT(CreateNewSegmentation()) ); connect( m_Controls->CreateSegmentationFromSurface, SIGNAL(clicked()), this, SLOT(CreateSegmentationFromSurface()) ); connect( m_Controls->m_ManualToolSelectionBox, SIGNAL(ToolSelected(int)), this, SLOT(ManualToolSelected(int)) ); connect( m_Controls->widgetStack, SIGNAL(currentChanged(int)), this, SLOT(ToolboxStackPageChanged(int)) ); connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSurfaceSelectionChanged( ) ) ); connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSurfaceSelectionChanged( ) ) ); connect(m_Controls->m_SlicesInterpolator, SIGNAL(SignalShowMarkerNodes(bool)), this, SLOT(OnShowMarkerNodes(bool))); connect(m_Controls->m_SlicesInterpolator, SIGNAL(Signal3DInterpolationEnabled(bool)), this, SLOT(On3DInterpolationEnabled(bool))); m_Controls->MaskSurfaces->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->MaskSurfaces->SetPredicate(mitk::NodePredicateDataType::New("Surface")); //// create helper class to provide context menus for segmentations in data manager // m_PostProcessing = new QmitkSegmentationPostProcessing(this->GetDefaultDataStorage(), this, m_Parent); } //void QmitkSegmentationView::OnPlaneModeChanged(int i) //{ // //if plane mode changes, disable all tools // if (m_MultiWidget) // { // mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); // // if (toolManager) // { // if (toolManager->GetActiveToolID() >= 0) // { // toolManager->ActivateTool(-1); // } // else // { // m_MultiWidget->EnableNavigationControllerEventListening(); // } // } // } //} // ATTENTION some methods for handling the known list of (organ names, colors) are defined in QmitkSegmentationOrganNamesHandling.cpp diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.cpp index 8ae4b2ceaf..4fc9977c98 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.cpp @@ -1,40 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkStatisticsAction.h" QmitkStatisticsAction::QmitkStatisticsAction(): m_BlueBerryView(NULL) { } QmitkStatisticsAction::~QmitkStatisticsAction() { } void QmitkStatisticsAction::Run(const QList& /*selectedNodes*/) { berry::IBundle::Pointer imageStatisticsBundle = berry::Platform::GetBundle("org.mitk.gui.qt.imagestatistics"); if (m_BlueBerryView && imageStatisticsBundle.IsNotNull()) { m_BlueBerryView->GetSite()->GetWorkbenchWindow()->GetActivePage()->ShowView("org.mitk.views.imagestatistics"); } } void QmitkStatisticsAction::SetFunctionality(berry::QtViewPart* functionality) { this->m_BlueBerryView = functionality; } void QmitkStatisticsAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) { //not needed } void QmitkStatisticsAction::SetSmoothed(bool /*smoothed*/) { //not needed } void QmitkStatisticsAction::SetDecimated(bool /*decimated*/) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h index 21a181da3a..cdd23c63ef 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h @@ -1,35 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITK_STATISTICSACTION_H #define QMITK_STATISTICSACTION_H #include #include "berryQtViewPart.h" #include "mitkIContextMenuAction.h" #include "org_mitk_gui_qt_segmentation_Export.h" class QmitkStdMultiWidget; class MITK_QT_SEGMENTATION QmitkStatisticsAction: public QObject, public mitk::IContextMenuAction { Q_OBJECT Q_INTERFACES(mitk::IContextMenuAction) public: QmitkStatisticsAction(); virtual ~QmitkStatisticsAction(); //interface methods void Run( const QList& selectedNodes ); void SetDataStorage(mitk::DataStorage* dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart* functionality); protected: //needs to be set over the IContextMenuAction (with this - QmitkDataManagerView - as parameter) berry::QtViewPart* m_BlueBerryView; }; #endif // QMITK_STATISTICSACTION_H diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp index 17cefd99c8..26bd96dd20 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp @@ -1,100 +1,115 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "QmitkThresholdAction.h" // MITK #include #include #include // Qt #include #include #include using namespace berry; using namespace mitk; using namespace std; QmitkThresholdAction::QmitkThresholdAction() : m_ThresholdingDialog(NULL) { } QmitkThresholdAction::~QmitkThresholdAction() { } void QmitkThresholdAction::Run(const QList &selectedNodes) { m_ThresholdingToolManager = ToolManager::New(m_DataStorage); m_ThresholdingToolManager->RegisterClient(); m_ThresholdingToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkThresholdAction::OnThresholdingToolManagerToolModified); m_ThresholdingDialog = new QDialog(QApplication::activeWindow()); connect(m_ThresholdingDialog, SIGNAL(finished(int)), this, SLOT(ThresholdingDone(int))); QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); Tool *binaryThresholdTool = m_ThresholdingToolManager->GetToolById(m_ThresholdingToolManager->GetToolIdByToolType()); if (binaryThresholdTool != NULL) { QmitkToolGUI *gui = dynamic_cast(binaryThresholdTool->GetGUI("Qmitk", "GUI").GetPointer()); if (gui != NULL) { gui->SetTool(binaryThresholdTool); gui->setParent(m_ThresholdingDialog); layout->addWidget(gui); m_ThresholdingDialog->setLayout(layout); m_ThresholdingDialog->setFixedSize(300, 80); m_ThresholdingDialog->open(); } m_ThresholdingToolManager->SetReferenceData(selectedNodes[0]); m_ThresholdingToolManager->ActivateTool(m_ThresholdingToolManager->GetToolIdByToolType()); } } void QmitkThresholdAction::ThresholdingDone(int result) { if (result == QDialog::Rejected) m_ThresholdingToolManager->ActivateTool(-1); m_ThresholdingDialog->deleteLater(); m_ThresholdingDialog = NULL; m_ThresholdingToolManager->SetReferenceData(NULL); m_ThresholdingToolManager->SetWorkingData(NULL); RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkThresholdAction::OnThresholdingToolManagerToolModified() { if (m_ThresholdingToolManager.IsNotNull()) if (m_ThresholdingToolManager->GetActiveToolID() < 0) if (m_ThresholdingDialog != NULL) m_ThresholdingDialog->accept(); } void QmitkThresholdAction::SetDataStorage(DataStorage *dataStorage) { m_DataStorage = dataStorage; } void QmitkThresholdAction::SetSmoothed(bool) { } void QmitkThresholdAction::SetDecimated(bool) { } void QmitkThresholdAction::SetFunctionality(QtViewPart* /*functionality*/) { } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h index 467469e44a..21c37f6150 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h @@ -1,47 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef QMITKTHRESHOLDACTION_H #define QMITKTHRESHOLDACTION_H #include // Parent classes #include #include // Data members #include #include class QDialog; class QmitkStdMultiWidget; class MITK_QT_SEGMENTATION QmitkThresholdAction : public QObject, public mitk::IContextMenuAction { Q_OBJECT Q_INTERFACES(mitk::IContextMenuAction) public: QmitkThresholdAction(); ~QmitkThresholdAction(); // IContextMenuAction void Run(const QList &selectedNodes); void SetDataStorage(mitk::DataStorage *dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart *functionality); void OnThresholdingToolManagerToolModified(); private slots: void ThresholdingDone(int); private: QmitkThresholdAction(const QmitkThresholdAction &); QmitkThresholdAction & operator=(const QmitkThresholdAction &); mitk::DataStorage::Pointer m_DataStorage; mitk::ToolManager::Pointer m_ThresholdingToolManager; QDialog *m_ThresholdingDialog; }; #endif diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp index 0a01e236da..08632fafa6 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp @@ -1,32 +1,47 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include "QmitkSegmentationView.h" #include "QmitkBooleanOperationsView.h" #include "QmitkThresholdAction.h" #include "QmitkCreatePolygonModelAction.h" #include "QmitkStatisticsAction.h" #include "QmitkAutocropAction.h" #include "QmitkSegmentationPreferencePage.h" #include "QmitkDeformableClippingPlaneView.h" #include "src/internal/regiongrowing/QmitkRegionGrowingView.h" using namespace mitk; void PluginActivator::start(ctkPluginContext *context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkBooleanOperationsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStatisticsAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDeformableClippingPlaneView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkRegionGrowingView, context); } void PluginActivator::stop(ctkPluginContext *) { } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_segmentation, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h index 9d7e77a2ad..e623d11a04 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h @@ -1,22 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H // Parent classes #include #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext *context); void stop(ctkPluginContext *context); }; } #endif diff --git a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.cpp index eccdae58c3..3a36bccdee 100644 --- a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.cpp @@ -1,20 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkToFTutorialView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkToFTutorialView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_toftutorial, mitk::PluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.h index 1646449674..f8fc02a880 100644 --- a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp index 51127b9dc8..7910c95b3e 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp @@ -1,520 +1,525 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkToFUtilView.h" #include #include // Qt #include #include // MITK #include #include #include #include #include #include // VTK #include // ITK #include const std::string QmitkToFUtilView::VIEW_ID = "org.mitk.views.tofutil"; QmitkToFUtilView::QmitkToFUtilView() : QmitkFunctionality() , m_Controls(NULL), m_MultiWidget( NULL ) , m_MitkDistanceImage(NULL), m_MitkAmplitudeImage(NULL), m_MitkIntensityImage(NULL), m_Surface(NULL) - , m_DistanceImageNode(NULL), m_AmplitudeImageNode(NULL), m_IntensityImageNode(NULL), m_SurfaceNode(NULL) + , m_DistanceImageNode(NULL), m_AmplitudeImageNode(NULL), m_IntensityImageNode(NULL), m_RGBImageNode(NULL), m_SurfaceNode(NULL) , m_ToFImageRecorder(NULL), m_ToFImageGrabber(NULL), m_ToFDistanceImageToSurfaceFilter(NULL), m_ToFCompositeFilter(NULL) , m_SurfaceDisplayCount(0), m_2DDisplayCount(0) , m_RealTimeClock(NULL) , m_StepsForFramerate(100) , m_2DTimeBefore(0.0) , m_2DTimeAfter(0.0) , m_VideoEnabled(false) { this->m_Frametimer = new QTimer(this); this->m_ToFDistanceImageToSurfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); this->m_ToFImageRecorder = mitk::ToFImageRecorder::New(); this->m_ToFSurfaceVtkMapper3D = mitk::ToFSurfaceVtkMapper3D::New(); } QmitkToFUtilView::~QmitkToFUtilView() { OnToFCameraStopped(); OnToFCameraDisconnected(); } void QmitkToFUtilView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkToFUtilViewControls; m_Controls->setupUi( parent ); connect(m_Frametimer, SIGNAL(timeout()), this, SLOT(OnUpdateCamera())); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraConnected()), this, SLOT(OnToFCameraConnected()) ); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraDisconnected()), this, SLOT(OnToFCameraDisconnected()) ); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraSelected(const QString)), this, SLOT(OnToFCameraSelected(const QString)) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStarted()), this, SLOT(OnToFCameraStarted()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStopped()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStarted()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStopped()), this, SLOT(OnToFCameraStarted()) ); connect( (QObject*)(m_Controls->m_TextureCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnTextureCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_VideoTextureCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnVideoTextureCheckBoxChecked(bool)) ); } } void QmitkToFUtilView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkToFUtilView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkToFUtilView::Activated() { QmitkFunctionality::Activated(); // configure views m_MultiWidget->SetWidgetPlanesVisibility(false); m_MultiWidget->mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Transversal); m_MultiWidget->mitkWidget1->GetSliceNavigationController()->SliceLockedOn(); m_MultiWidget->mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Transversal); m_MultiWidget->mitkWidget2->GetSliceNavigationController()->SliceLockedOn(); m_MultiWidget->mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Transversal); m_MultiWidget->mitkWidget3->GetSliceNavigationController()->SliceLockedOn(); m_MultiWidget->ResetCrosshair(); mitk::RenderingManager::GetInstance()->InitializeViews(); this->UseToFVisibilitySettings(true); m_Controls->m_ToFCompositeFilterWidget->SetToFCompositeFilter(this->m_ToFCompositeFilter); m_Controls->m_ToFCompositeFilterWidget->SetDataStorage(this->GetDefaultDataStorage()); if (this->m_ToFImageGrabber.IsNull()) { m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); } } void QmitkToFUtilView::Deactivated() { m_MultiWidget->SetWidgetPlanesVisibility(true); m_MultiWidget->mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Transversal); m_MultiWidget->mitkWidget1->GetSliceNavigationController()->SliceLockedOff(); m_MultiWidget->mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); m_MultiWidget->mitkWidget2->GetSliceNavigationController()->SliceLockedOff(); m_MultiWidget->mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); m_MultiWidget->mitkWidget3->GetSliceNavigationController()->SliceLockedOff(); m_MultiWidget->ResetCrosshair(); this->UseToFVisibilitySettings(false); mitk::RenderingManager::GetInstance()->InitializeViews(); QmitkFunctionality::Deactivated(); } void QmitkToFUtilView::OnToFCameraConnected() { this->m_SurfaceDisplayCount = 0; this->m_2DDisplayCount = 0; this->m_ToFImageGrabber = m_Controls->m_ToFConnectionWidget->GetToFImageGrabber(); this->m_ToFImageRecorder->SetCameraDevice(this->m_ToFImageGrabber->GetCameraDevice()); m_Controls->m_ToFRecorderWidget->SetParameter(this->m_ToFImageGrabber, this->m_ToFImageRecorder); m_Controls->m_ToFRecorderWidget->setEnabled(true); m_Controls->m_ToFRecorderWidget->ResetGUIToInitial(); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(true); //TODO this->m_RealTimeClock = mitk::RealTimeClock::New(); this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); try { this->m_VideoSource = mitk::OpenCVVideoSource::New(); this->m_VideoSource->SetVideoCameraInput(0, false); this->m_VideoSource->StartCapturing(); if(!this->m_VideoSource->IsCapturingEnabled()) { - MITK_INFO << "unable to initialize video grabbing/playback"; + MITK_INFO << "unable to initialize video grabbing/playback, probably not video camera connected"; this->m_VideoEnabled = false; m_Controls->m_VideoTextureCheckBox->setEnabled(false); } else { this->m_VideoEnabled = true; m_Controls->m_VideoTextureCheckBox->setEnabled(true); } if (this->m_VideoEnabled) { this->m_VideoSource->FetchFrame(); this->m_VideoCaptureHeight = this->m_VideoSource->GetImageHeight(); this->m_VideoCaptureWidth = this->m_VideoSource->GetImageWidth(); int videoTexSize = this->m_VideoCaptureWidth * this->m_VideoCaptureHeight * 3; // for each pixel three values for rgb are needed!! this->m_VideoTexture = this->m_VideoSource->GetVideoTexture(); unsigned int dimensions[2]; dimensions[0] = this->m_VideoCaptureWidth; dimensions[1] = this->m_VideoCaptureHeight; this->m_ToFDistanceImageToSurfaceFilter->SetTextureImageWidth(this->m_VideoCaptureWidth); this->m_ToFDistanceImageToSurfaceFilter->SetTextureImageHeight(this->m_VideoCaptureHeight); this->m_ToFSurfaceVtkMapper3D->SetTextureWidth(this->m_VideoCaptureWidth); this->m_ToFSurfaceVtkMapper3D->SetTextureHeight(this->m_VideoCaptureHeight); } m_MultiWidget->DisableGradientBackground(); } catch (std::logic_error& e) { QMessageBox::warning(NULL, "Warning", QString(e.what())); MITK_ERROR << e.what(); return; } mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } void QmitkToFUtilView::OnToFCameraDisconnected() { m_Controls->m_ToFRecorderWidget->OnStop(); m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); if(this->m_VideoSource) { this->m_VideoSource->StopCapturing(); this->m_VideoSource = NULL; } mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } void QmitkToFUtilView::OnToFCameraStarted() { - if (m_ToFImageGrabber.IsNotNull()) + if (m_ToFImageGrabber.IsNotNull()) + { + // initial update of image grabber + this->m_ToFImageGrabber->Update(); + + this->m_ToFCompositeFilter->SetInput(0,this->m_ToFImageGrabber->GetOutput(0)); + this->m_ToFCompositeFilter->SetInput(1,this->m_ToFImageGrabber->GetOutput(1)); + this->m_ToFCompositeFilter->SetInput(2,this->m_ToFImageGrabber->GetOutput(2)); + + // initial update of composite filter + this->m_ToFCompositeFilter->Update(); + this->m_MitkDistanceImage = m_ToFCompositeFilter->GetOutput(0); + this->m_DistanceImageNode = ReplaceNodeData("Distance image",m_MitkDistanceImage); + this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); + this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); + this->m_MitkIntensityImage = m_ToFCompositeFilter->GetOutput(2); + this->m_IntensityImageNode = ReplaceNodeData("Intensity image",m_MitkIntensityImage); + + std::string rgbFileName; + m_ToFImageGrabber->GetCameraDevice()->GetStringProperty("RGBImageFileName",rgbFileName); + if ((m_SelectedCamera=="Microsoft Kinect")||(rgbFileName!="")) { - // initial update of image grabber - this->m_ToFImageGrabber->Update(); - - this->m_ToFCompositeFilter->SetInput(0,this->m_ToFImageGrabber->GetOutput(0)); - this->m_ToFCompositeFilter->SetInput(1,this->m_ToFImageGrabber->GetOutput(1)); - this->m_ToFCompositeFilter->SetInput(2,this->m_ToFImageGrabber->GetOutput(2)); - // initial update of composite filter - this->m_ToFCompositeFilter->Update(); - this->m_MitkDistanceImage = m_ToFCompositeFilter->GetOutput(0); - this->m_DistanceImageNode = ReplaceNodeData("Distance image",m_MitkDistanceImage); - this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); - this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); - this->m_MitkIntensityImage = m_ToFCompositeFilter->GetOutput(2); - this->m_IntensityImageNode = ReplaceNodeData("Intensity image",m_MitkIntensityImage); - - this->m_ToFDistanceImageToSurfaceFilter->SetInput(0,m_MitkDistanceImage); - this->m_ToFDistanceImageToSurfaceFilter->SetInput(1,m_MitkAmplitudeImage); - this->m_ToFDistanceImageToSurfaceFilter->SetInput(2,m_MitkIntensityImage); - this->m_Surface = this->m_ToFDistanceImageToSurfaceFilter->GetOutput(0); - this->m_SurfaceNode = ReplaceNodeData("Surface",m_Surface); - - this->UseToFVisibilitySettings(true); - - this->m_Frametimer->start(0); - - m_Controls->m_ToFCompositeFilterWidget->UpdateFilterParameter(); - // initialize visualization widget - m_Controls->m_ToFVisualisationSettingsWidget->Initialize(this->m_MitkDistanceImage, this->m_MitkAmplitudeImage, this->m_MitkIntensityImage); - - if (m_Controls->m_TextureCheckBox->isChecked()) - { - OnTextureCheckBoxChecked(true); - } - if (m_Controls->m_VideoTextureCheckBox->isChecked()) - { - OnVideoTextureCheckBoxChecked(true); - } + this->m_RGBImageNode = ReplaceNodeData("RGB image",this->m_ToFImageGrabber->GetOutput(3)); } - m_Controls->m_TextureCheckBox->setEnabled(true); - // initialize point set measurement - m_Controls->tofMeasurementWidget->InitializeWidget(m_MultiWidget,this->GetDefaultDataStorage(),m_MitkDistanceImage); + else + { + this->m_RGBImageNode = NULL; + } + + this->m_ToFDistanceImageToSurfaceFilter->SetInput(0,m_MitkDistanceImage); + this->m_ToFDistanceImageToSurfaceFilter->SetInput(1,m_MitkAmplitudeImage); + this->m_ToFDistanceImageToSurfaceFilter->SetInput(2,m_MitkIntensityImage); + this->m_Surface = this->m_ToFDistanceImageToSurfaceFilter->GetOutput(0); + this->m_SurfaceNode = ReplaceNodeData("Surface",m_Surface); + + this->UseToFVisibilitySettings(true); + + m_Controls->m_ToFCompositeFilterWidget->UpdateFilterParameter(); + // initialize visualization widget + m_Controls->m_ToFVisualisationSettingsWidget->Initialize(this->m_DistanceImageNode, this->m_AmplitudeImageNode, this->m_IntensityImageNode); + + this->m_Frametimer->start(0); + + if (m_Controls->m_TextureCheckBox->isChecked()) + { + OnTextureCheckBoxChecked(true); + } + if (m_Controls->m_VideoTextureCheckBox->isChecked()) + { + OnVideoTextureCheckBoxChecked(true); + } + } + m_Controls->m_TextureCheckBox->setEnabled(true); + // initialize point set measurement + m_Controls->tofMeasurementWidget->InitializeWidget(m_MultiWidget,this->GetDefaultDataStorage(),m_MitkDistanceImage); } void QmitkToFUtilView::OnToFCameraStopped() { - this->m_Frametimer->stop(); + this->m_Frametimer->stop(); } void QmitkToFUtilView::OnToFCameraSelected(const QString selected) { - if ((selected=="PMD CamBoard")||(selected=="PMD O3D")) - { - MITK_INFO<<"Surface representation currently not available for CamBoard and O3. Intrinsic parameters missing."; - this->m_Controls->m_SurfaceCheckBox->setEnabled(false); - this->m_Controls->m_TextureCheckBox->setEnabled(false); - this->m_Controls->m_VideoTextureCheckBox->setEnabled(false); - this->m_Controls->m_SurfaceCheckBox->setChecked(false); - this->m_Controls->m_TextureCheckBox->setChecked(false); + m_SelectedCamera = selected; + if ((selected=="PMD CamBoard")||(selected=="PMD O3D")) + { + MITK_INFO<<"Surface representation currently not available for CamBoard and O3. Intrinsic parameters missing."; + this->m_Controls->m_SurfaceCheckBox->setEnabled(false); + this->m_Controls->m_TextureCheckBox->setEnabled(false); + this->m_Controls->m_VideoTextureCheckBox->setEnabled(false); + this->m_Controls->m_SurfaceCheckBox->setChecked(false); + this->m_Controls->m_TextureCheckBox->setChecked(false); this->m_Controls->m_VideoTextureCheckBox->setChecked(false); } else { this->m_Controls->m_SurfaceCheckBox->setEnabled(true); this->m_Controls->m_TextureCheckBox->setEnabled(true); // TODO enable when bug 8106 is solved this->m_Controls->m_VideoTextureCheckBox->setEnabled(true); } } void QmitkToFUtilView::OnUpdateCamera() { if (m_Controls->m_VideoTextureCheckBox->isChecked() && this->m_VideoEnabled && this->m_VideoSource) { this->m_VideoTexture = this->m_VideoSource->GetVideoTexture(); ProcessVideoTransform(); } - vtkColorTransferFunction* colorTransferFunction1; - colorTransferFunction1 = m_Controls->m_ToFVisualisationSettingsWidget->GetWidget1ColorTransferFunction(); - mitk::TransferFunction::Pointer tf1 = mitk::TransferFunction::New(); - tf1->SetColorTransferFunction( colorTransferFunction1 ); - m_DistanceImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf1)); - vtkColorTransferFunction* colorTransferFunction2; - colorTransferFunction2 = m_Controls->m_ToFVisualisationSettingsWidget->GetWidget2ColorTransferFunction(); - mitk::TransferFunction::Pointer tf2 = mitk::TransferFunction::New(); - tf2->SetColorTransferFunction( colorTransferFunction2 ); - m_AmplitudeImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf2)); - vtkColorTransferFunction* colorTransferFunction3; - colorTransferFunction3 = m_Controls->m_ToFVisualisationSettingsWidget->GetWidget3ColorTransferFunction(); - mitk::TransferFunction::Pointer tf3 = mitk::TransferFunction::New(); - tf3->SetColorTransferFunction( colorTransferFunction3 ); - m_IntensityImageNode->SetProperty("Image Rendering.Transfer Function",mitk::TransferFunctionProperty::New(tf3)); - if (m_Controls->m_SurfaceCheckBox->isChecked()) { // update surface m_ToFDistanceImageToSurfaceFilter->SetTextureIndex(m_Controls->m_ToFVisualisationSettingsWidget->GetSelectedImageIndex()); this->m_Surface->Update(); vtkColorTransferFunction* colorTransferFunction = m_Controls->m_ToFVisualisationSettingsWidget->GetSelectedColorTransferFunction(); this->m_ToFSurfaceVtkMapper3D->SetVtkScalarsToColors(colorTransferFunction); if (this->m_SurfaceDisplayCount<2) { this->m_SurfaceNode->SetData(this->m_Surface); this->m_SurfaceNode->SetMapper(mitk::BaseRenderer::Standard3D, m_ToFSurfaceVtkMapper3D); mitk::RenderingManager::GetInstance()->InitializeViews( this->m_Surface->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS, true); mitk::Point3D surfaceCenter= this->m_Surface->GetGeometry()->GetCenter(); m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(0,0,-50); m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(0,-1,0); m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(0,0,surfaceCenter[2]); m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewAngle(40); m_MultiWidget->mitkWidget4->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetClippingRange(1, 10000); } this->m_SurfaceDisplayCount++; } else { // update pipeline this->m_MitkDistanceImage->Update(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->m_2DDisplayCount++; if ((this->m_2DDisplayCount % this->m_StepsForFramerate) == 0) { this->m_2DTimeAfter = this->m_RealTimeClock->GetCurrentStamp() - this->m_2DTimeBefore; MITK_INFO << " 2D-Display-framerate (fps): " << this->m_StepsForFramerate / (this->m_2DTimeAfter/1000); this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); } } void QmitkToFUtilView::ProcessVideoTransform() { IplImage *src, *dst; src = cvCreateImageHeader(cvSize(this->m_VideoCaptureWidth, this->m_VideoCaptureHeight), IPL_DEPTH_8U, 3); src->imageData = (char*)this->m_VideoTexture; CvPoint2D32f srcTri[3], dstTri[3]; CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1); CvMat* warp_mat = cvCreateMat(2,3,CV_32FC1); dst = cvCloneImage(src); dst->origin = src->origin; cvZero( dst ); int xOffset = 0;//m_Controls->m_XOffsetSpinBox->value(); int yOffset = 0;//m_Controls->m_YOffsetSpinBox->value(); int zoom = 0;//m_Controls->m_ZoomSpinBox->value(); // Compute warp matrix srcTri[0].x = 0 + zoom; srcTri[0].y = 0 + zoom; srcTri[1].x = src->width - 1 - zoom; srcTri[1].y = 0 + zoom; srcTri[2].x = 0 + zoom; srcTri[2].y = src->height - 1 - zoom; dstTri[0].x = 0; dstTri[0].y = 0; dstTri[1].x = src->width - 1; dstTri[1].y = 0; dstTri[2].x = 0; dstTri[2].y = src->height - 1; cvGetAffineTransform( srcTri, dstTri, warp_mat ); cvWarpAffine( src, dst, warp_mat ); cvCopy ( dst, src ); // Compute warp matrix srcTri[0].x = 0; srcTri[0].y = 0; srcTri[1].x = src->width - 1; srcTri[1].y = 0; srcTri[2].x = 0; srcTri[2].y = src->height - 1; dstTri[0].x = srcTri[0].x + xOffset; dstTri[0].y = srcTri[0].y + yOffset; dstTri[1].x = srcTri[1].x + xOffset; dstTri[1].y = srcTri[1].y + yOffset; dstTri[2].x = srcTri[2].x + xOffset; dstTri[2].y = srcTri[2].y + yOffset; cvGetAffineTransform( srcTri, dstTri, warp_mat ); cvWarpAffine( src, dst, warp_mat ); cvCopy ( dst, src ); src->imageData = NULL; cvReleaseImage( &src ); cvReleaseImage( &dst ); cvReleaseMat( &rot_mat ); cvReleaseMat( &warp_mat ); } void QmitkToFUtilView::OnTextureCheckBoxChecked(bool checked) { if(m_SurfaceNode.IsNotNull()) { if (checked) { this->m_SurfaceNode->SetBoolProperty("scalar visibility", true); } else { this->m_SurfaceNode->SetBoolProperty("scalar visibility", false); } } } void QmitkToFUtilView::OnVideoTextureCheckBoxChecked(bool checked) { if (checked) { if (this->m_VideoEnabled) { this->m_ToFSurfaceVtkMapper3D->SetTexture(this->m_VideoTexture); } else { this->m_ToFSurfaceVtkMapper3D->SetTexture(NULL); } } else { this->m_ToFSurfaceVtkMapper3D->SetTexture(NULL); } } mitk::DataNode::Pointer QmitkToFUtilView::ReplaceNodeData( std::string nodeName, mitk::BaseData* data ) { mitk::DataNode::Pointer node = this->GetDefaultDataStorage()->GetNamedNode(nodeName); if (node.IsNull()) { node = mitk::DataNode::New(); node->SetData(data); node->SetName(nodeName); + node->SetBoolProperty("binary",false); this->GetDefaultDataStorage()->Add(node); } else { node->SetData(data); } return node; } void QmitkToFUtilView::UseToFVisibilitySettings(bool useToF) { // set node properties if (m_DistanceImageNode.IsNotNull()) { this->m_DistanceImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget2->GetRenderWindow() ) ); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget3->GetRenderWindow() ) ); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget4->GetRenderWindow() ) ); this->m_DistanceImageNode->SetBoolProperty("use color",!useToF); this->m_DistanceImageNode->GetPropertyList()->DeleteProperty("LookupTable"); } if (m_AmplitudeImageNode.IsNotNull()) { this->m_AmplitudeImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget1->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget3->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget4->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetBoolProperty("use color",!useToF); this->m_AmplitudeImageNode->GetPropertyList()->DeleteProperty("LookupTable"); } if (m_IntensityImageNode.IsNotNull()) { this->m_IntensityImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget1->GetRenderWindow() ) ); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget2->GetRenderWindow() ) ); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget4->GetRenderWindow() ) ); this->m_IntensityImageNode->SetBoolProperty("use color",!useToF); this->m_IntensityImageNode->GetPropertyList()->DeleteProperty("LookupTable"); } + if ((m_RGBImageNode.IsNotNull())) + { + this->m_RGBImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget1->GetRenderWindow() ) ); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget2->GetRenderWindow() ) ); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetActiveStdMultiWidget()->mitkWidget4->GetRenderWindow() ) ); + } // initialize images if (m_MitkDistanceImage.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( this->m_MitkDistanceImage->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS, true); } } diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h index fde34de736..170c091911 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h @@ -1,169 +1,172 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkToFUtilView_h #define QmitkToFUtilView_h #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief QmitkToFUtilView Application that allows simple playing, recording, visualization, processing and measurement of Time-of-Flight (ToF) data. Currently the following features are implemented:
  • Connecting and showing ToF data from various cameras (PMD CamCube 2/3, PMD CamBoard, PMD O3, MESA SwissRanger)
  • Recording and playing of ToF data
  • Color coded visualization of ToF images
  • Preprocessing of the distance data: Threshold, median, average and bilateral filtering; surface generation
  • Simple measurement and PointSet definition
\sa QmitkFunctionality \ingroup Functionalities */ class QmitkToFUtilView : public QmitkFunctionality { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFUtilView(); ~QmitkToFUtilView(); virtual void CreateQtPartControl(QWidget *parent); /// \brief Called when the functionality is activated virtual void Activated(); /// \brief Called when the functionality is deactivated virtual void Deactivated(); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); protected slots: /*! \brief Slot triggered from the timer to update the images and visualization */ void OnUpdateCamera(); /*! \brief Slot called when the "Connect" button of the ConnectionWidget is pressed */ void OnToFCameraConnected(); /*! \brief Slot called when the "Disconnect" button of the ConnectionWidget is pressed */ void OnToFCameraDisconnected(); /*! \brief Slot called when the camera selection in the ConnectionWidget has changed */ void OnToFCameraSelected(const QString selected); /*! \brief Slot called when the "Start" button of the RecorderWidget is pressed */ void OnToFCameraStarted(); /*! \brief Slot called when the "Stop" button of the RecorderWidget is pressed */ void OnToFCameraStopped(); /*! \brief Slot invoked when the texture checkbox is checked. Enables the scalar visibility of the surface */ void OnTextureCheckBoxChecked(bool checked); /*! \brief Slot invoked when the video texture checkbox is checked. Enables the texture of the surface */ void OnVideoTextureCheckBoxChecked(bool checked); protected: /*! \brief initialize the visibility settings of ToF data (images + surface) \param useToF true: distance image: widget1, amplitude image: widget 2, intensity image: widget 3; false: standard */ void UseToFVisibilitySettings(bool useToF); Ui::QmitkToFUtilViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; QTimer* m_Frametimer; ///< Timer used to continuously update the images + QString m_SelectedCamera; ///< String holding the selected camera + mitk::Image::Pointer m_MitkDistanceImage; ///< member holding a pointer to the distance image of the selected camera mitk::Image::Pointer m_MitkAmplitudeImage; ///< member holding a pointer to the amplitude image of the selected camera mitk::Image::Pointer m_MitkIntensityImage; ///< member holding a pointer to the intensity image of the selected camera mitk::Surface::Pointer m_Surface; ///< member holding a pointer to the surface generated from the distance image of the selected camera mitk::DataNode::Pointer m_DistanceImageNode; ///< DataNode holding the distance image of the selected camera mitk::DataNode::Pointer m_AmplitudeImageNode; ///< DataNode holding the amplitude image of the selected camera mitk::DataNode::Pointer m_IntensityImageNode; ///< DataNode holding the intensity image of the selected camera + mitk::DataNode::Pointer m_RGBImageNode; ///< DataNode holding the rgb image of the selected camera mitk::DataNode::Pointer m_SurfaceNode; ///< DataNode holding the surface generated from the distanc image of the selected camera // ToF processing and recording filter mitk::ToFImageRecorder::Pointer m_ToFImageRecorder; ///< ToF image recorder used for lossless recording of ToF image data mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< Source of a ToF image processing pipeline. Provides pointers to distance, amplitude and intensity image mitk::ToFDistanceImageToSurfaceFilter::Pointer m_ToFDistanceImageToSurfaceFilter; ///< Filter for calculating a surface representation from a given distance image mitk::ToFCompositeFilter::Pointer m_ToFCompositeFilter; ///< Filter combining several processing steps (thresholding, Median filtering, Bilateral filtering) int m_SurfaceDisplayCount; ///< member used to determine whether surface is initialized or not int m_2DDisplayCount; ///< member used to determine whether frame rate output should be shown // members for calculating the frame rate mitk::RealTimeClock::Pointer m_RealTimeClock; ///< real time clock used to calculate the display framerate int m_StepsForFramerate; ///< number of steps used for calculating the display framerate double m_2DTimeBefore; ///< holds the time stamp at the beginning of the display framerate measurement double m_2DTimeAfter; ///< holds the time stamp at the end of the display framerate measurement // members used for displaying an external video source mitk::OpenCVVideoSource::Pointer m_VideoSource; ///< OpenCV video source to connect a video device unsigned char* m_VideoTexture; ///< texture used to show video image int m_VideoCaptureWidth; ///< width of the video image int m_VideoCaptureHeight; ///< height of the video image bool m_VideoEnabled; ///< flag indicating whether video grabbing is enabled. Set via the RGB texture checkbox private: /*! \brief helper method to replace data of the specified node. If node does not exist it will be created \param nodeName Name of the node \param data Data object to be replaced \return returns the node */ mitk::DataNode::Pointer ReplaceNodeData(std::string nodeName, mitk::BaseData* data); void ProcessVideoTransform(); mitk::ToFSurfaceVtkMapper3D::Pointer m_ToFSurfaceVtkMapper3D; }; #endif // _QMITKTOFUTILVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.cpp index 1ddbdb1a9d..f643e95240 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.cpp @@ -1,20 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkToFUtilView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkToFUtilView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_tofutil, mitk::PluginActivator) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.h index 1646449674..f8fc02a880 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.cpp index 921aface47..2650e24474 100644 --- a/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkUGVisualizationView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkUGVisualizationView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_ugvisualization, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.h index 0436a647ad..ca951ddd3f 100644 --- a/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.ugvisualization/src/internal/mitkPluginActivator.h @@ -1,25 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.cpp index 4797896e23..c40c7c1632 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.cpp @@ -1,21 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkVolumeVisualizationView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkVolumeVisualizationView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_volumevisualization, mitk::PluginActivator) diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.h index aabb457032..dc7ad4f70c 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.h +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/mitkPluginActivator.h @@ -1,24 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ #ifndef MITKPLUGINACTIVATOR_H #define MITKPLUGINACTIVATOR_H #include #include namespace mitk { class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); }; // PluginActivator } #endif // MITKPLUGINACTIVATOR_H