<commit_before>#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <QtCore/QSocketNotifier>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtCore/QWaitCondition>
#include "virtualserialdevice.h"

namespace SymbianUtils {

class VirtualSerialDevicePrivate
{
public:
    int portHandle;
    QSocketNotifier* readNotifier;
    QSocketNotifier* writeUnblockedNotifier;
};

void VirtualSerialDevice::platInit()
{
    d = new VirtualSerialDevicePrivate;
    d->portHandle = -1;
    d->readNotifier = NULL;
    d->writeUnblockedNotifier = NULL;
    connect(this, SIGNAL(AsyncCall_emitBytesWrittenIfNeeded(qint64)), this, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection);
}

bool VirtualSerialDevice::open(OpenMode mode)
{
    if (isOpen()) return true;

    d->portHandle = ::open(portName.toAscii().constData(), O_RDWR | O_NONBLOCK | O_NOCTTY);
    if (d->portHandle == -1) {
        setErrorString(QString("Posix error %1 opening %2").arg(errno).arg(portName));
        return false;
        }

    d->readNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Read);
    connect(d->readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead()));

    d->writeUnblockedNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Write);
    d->writeUnblockedNotifier->setEnabled(false);
    connect(d->writeUnblockedNotifier, SIGNAL(activated(int)), this, SLOT(writeHasUnblocked(int)));

    bool ok = QIODevice::open(mode);
    if (!ok) close();
    return ok;
}

void VirtualSerialDevice::platClose()
{
    delete d->readNotifier;
    d->readNotifier = NULL;

    delete d->writeUnblockedNotifier;
    d->writeUnblockedNotifier = NULL;

    ::close(d->portHandle);
    d->portHandle = -1;
}

VirtualSerialDevice::~VirtualSerialDevice()
{
    close();
    delete d;
}

qint64 VirtualSerialDevice::bytesAvailable() const
{
    QMutexLocker locker(&lock);
    if (!isOpen()) return 0;

    int avail = 0;
    if (ioctl(d->portHandle, FIONREAD, &avail) == -1) {
        return 0;
    }
    return (qint64)avail + QIODevice::bytesAvailable();
}

qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    int result = ::read(d->portHandle, data, maxSize);
    if (result == -1 && errno == EAGAIN)
        result = 0; // To Qt, 0 here means nothing ready right now, and -1 is reserved for permanent errors
    return result;
}

qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    qint64 bytesWritten;
    bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync);
    if (!needToWait) {
        needToWait = tryWrite(data, maxSize, bytesWritten);
        if (needToWait && bytesWritten > 0) {
            // Wrote some of the buffer, adjust pointers to point to the remainder that needs queueing
            data += bytesWritten;
            maxSize -= bytesWritten;
        }
    }

    if (needToWait) {
        pendingWrites.append(QByteArray(data, maxSize));
        d->writeUnblockedNotifier->setEnabled(true);
        // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten
        return bytesWritten + maxSize;
    } else {
        //emitBytesWrittenIfNeeded(locker, bytesWritten);
        // Can't emit bytesWritten directly from writeData - means clients end up recursing
        emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
        return bytesWritten;
    }
}

/* Returns true if EAGAIN encountered.
 * if error occurred (other than EAGAIN) returns -1 in bytesWritten
 * lock must be held. Doesn't emit signals or set notifiers.
 */
bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& bytesWritten)
{
    // Must be locked
    bytesWritten = 0;
    while (maxSize > 0) {
        int result = ::write(d->portHandle, data, maxSize);
        if (result == -1) {
            if (errno == EAGAIN)
                return true; // Need to wait
            setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName));
            bytesWritten = -1;
            return false;
        } else {
            if (result == 0)
                qWarning("Zero bytes written to port!");
            bytesWritten += result;
            maxSize -= result;
            data += result;
        }
    }
    return false; // If we reach here we've successfully written all the data without blocking
}

/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written.
 * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than
 * attempting to drain the whole queue.
 * Doesn't modify notifier.
 */
bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags)
{
    while (pendingWrites.count() > 0) {
        // Try writing everything we've got, until we hit EAGAIN
        const QByteArray& data = pendingWrites[0];
        qint64 bytesWritten;
        bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten);
        if (needToWait) {
            if (bytesWritten > 0) {
                // We wrote some of the data, update the pending queue
                QByteArray remainder = data.mid(bytesWritten);
                pendingWrites.removeFirst();
                pendingWrites.insert(0, remainder);
            }
            return needToWait;
        } else {
            pendingWrites.removeFirst();
            if (flags & EmitBytesWrittenAsync) {
                emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
            } else {
                emitBytesWrittenIfNeeded(locker, bytesWritten);
            }
            if (flags & StopAfterWritingOneBuffer) return false;
            // Otherwise go round loop again
        }
    }
    return false; // no EAGAIN encountered
}

void VirtualSerialDevice::writeHasUnblocked(int fileHandle)
{
    Q_ASSERT(fileHandle == d->portHandle);
    (void)fileHandle; // Compiler shutter-upper
    d->writeUnblockedNotifier->setEnabled(false);

    QMutexLocker locker(&lock);
    bool needToWait = tryFlushPendingBuffers(locker);
    if (needToWait) d->writeUnblockedNotifier->setEnabled(true);
}

// Copy of qt_safe_select from /qt/src/corelib/kernel/qeventdispatcher_unix.cpp
// But without the timeout correction
int safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
                   const struct timeval *orig_timeout)
{
    if (!orig_timeout) {
        // no timeout -> block forever
        register int ret;
        do {
            ret = select(nfds, fdread, fdwrite, fdexcept, 0);
        } while (ret == -1 && errno == EINTR);
        return ret;
    }

    timeval timeout = *orig_timeout;

    int ret;
    forever {
        ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
        if (ret != -1 || errno != EINTR)
            return ret;
    }
}

bool VirtualSerialDevice::waitForBytesWritten(int msecs)
{
    QMutexLocker locker(&lock);
    if (pendingWrites.count() == 0) return false;

    if (QThread::currentThread() != thread()) {
        // Wait for signal from main thread
        unsigned long timeout = msecs;
        if (msecs == -1) timeout = ULONG_MAX;
        if (waiterForBytesWritten == NULL)
            waiterForBytesWritten = new QWaitCondition;
        return waiterForBytesWritten->wait(&lock, timeout);
    }

    d->writeUnblockedNotifier->setEnabled(false);
    forever {
        fd_set writeSet;
        FD_ZERO(&writeSet);
        FD_SET(d->portHandle, &writeSet);

        struct timeval timeout;
        if (msecs != -1) {
            timeout.tv_sec = msecs / 1000;
            timeout.tv_usec = (msecs % 1000) * 1000;
        }
        int ret = safe_select(d->portHandle+1, NULL, &writeSet, NULL, msecs == -1 ? NULL : &timeout);

        if (ret == 0) {
            // Timeout
            return false;
        } else if (ret < 0) {
            setErrorString(QString("Posix error %1 returned from select in waitForBytesWritten").arg(errno));
            return false;
        } else {
            bool needToWait = tryFlushPendingBuffers(locker, StopAfterWritingOneBuffer);
            if (needToWait) {
                // go round the select again
            } else {
                return true;
            }
        }
    }
}

void VirtualSerialDevice::flush()
{
    while (waitForBytesWritten(-1)) { /* loop */ }
    tcflush(d->portHandle, TCIOFLUSH);
}

bool VirtualSerialDevice::waitForReadyRead(int msecs)
{
    return QIODevice::waitForReadyRead(msecs); //TODO
}

} // namespace SymbianUtils
<commit_msg>Symbian: Fix for CODA serial problem on unix<commit_after>#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <QtCore/QSocketNotifier>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtCore/QWaitCondition>
#include "virtualserialdevice.h"

namespace SymbianUtils {

class VirtualSerialDevicePrivate
{
public:
    int portHandle;
    QSocketNotifier* readNotifier;
    QSocketNotifier* writeUnblockedNotifier;
};

void VirtualSerialDevice::platInit()
{
    d = new VirtualSerialDevicePrivate;
    d->portHandle = -1;
    d->readNotifier = NULL;
    d->writeUnblockedNotifier = NULL;
    connect(this, SIGNAL(AsyncCall_emitBytesWrittenIfNeeded(qint64)), this, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection);
}

bool VirtualSerialDevice::open(OpenMode mode)
{
    if (isOpen()) return true;

    d->portHandle = ::open(portName.toAscii().constData(), O_RDWR | O_NONBLOCK | O_NOCTTY);
    if (d->portHandle == -1) {
        setErrorString(QString("Posix error %1 opening %2").arg(errno).arg(portName));
        return false;
        }

    struct termios termInfo;
    if (tcgetattr(d->portHandle, &termInfo) < 0) {
        setErrorString(QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))));
        close();
        return false;
    }
    cfmakeraw(&termInfo);
    // Turn off terminal echo as not get messages back, among other things
    termInfo.c_cflag |= CREAD|CLOCAL;
    termInfo.c_cc[VTIME] = 0;
    termInfo.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
    termInfo.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY|IXON|IXOFF));
    termInfo.c_oflag &= (~OPOST);
    termInfo.c_cc[VMIN]  = 0;
    termInfo.c_cc[VINTR] = _POSIX_VDISABLE;
    termInfo.c_cc[VQUIT] = _POSIX_VDISABLE;
    termInfo.c_cc[VSTART] = _POSIX_VDISABLE;
    termInfo.c_cc[VSTOP] = _POSIX_VDISABLE;
    termInfo.c_cc[VSUSP] = _POSIX_VDISABLE;

    if (tcsetattr(d->portHandle, TCSAFLUSH, &termInfo) < 0) {
        setErrorString(QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))));
        close();
        return false;
    }

    d->readNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Read);
    connect(d->readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead()));

    d->writeUnblockedNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Write);
    d->writeUnblockedNotifier->setEnabled(false);
    connect(d->writeUnblockedNotifier, SIGNAL(activated(int)), this, SLOT(writeHasUnblocked(int)));

    bool ok = QIODevice::open(mode | QIODevice::Unbuffered);
    if (!ok) close();
    return ok;
}

void VirtualSerialDevice::platClose()
{
    delete d->readNotifier;
    d->readNotifier = NULL;

    delete d->writeUnblockedNotifier;
    d->writeUnblockedNotifier = NULL;

    ::close(d->portHandle);
    d->portHandle = -1;
}

VirtualSerialDevice::~VirtualSerialDevice()
{
    close();
    delete d;
}

qint64 VirtualSerialDevice::bytesAvailable() const
{
    QMutexLocker locker(&lock);
    if (!isOpen()) return 0;

    int avail = 0;
    if (ioctl(d->portHandle, FIONREAD, &avail) == -1) {
        return 0;
    }
    return (qint64)avail + QIODevice::bytesAvailable();
}

qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    int result = ::read(d->portHandle, data, maxSize);
    if (result == -1 && errno == EAGAIN)
        result = 0; // To Qt, 0 here means nothing ready right now, and -1 is reserved for permanent errors
    return result;
}

qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    qint64 bytesWritten;
    bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync);
    if (!needToWait) {
        needToWait = tryWrite(data, maxSize, bytesWritten);
        if (needToWait && bytesWritten > 0) {
            // Wrote some of the buffer, adjust pointers to point to the remainder that needs queueing
            data += bytesWritten;
            maxSize -= bytesWritten;
        }
    }

    if (needToWait) {
        pendingWrites.append(QByteArray(data, maxSize));
        d->writeUnblockedNotifier->setEnabled(true);
        // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten
        return bytesWritten + maxSize;
    } else {
        //emitBytesWrittenIfNeeded(locker, bytesWritten);
        // Can't emit bytesWritten directly from writeData - means clients end up recursing
        emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
        return bytesWritten;
    }
}

/* Returns true if EAGAIN encountered.
 * if error occurred (other than EAGAIN) returns -1 in bytesWritten
 * lock must be held. Doesn't emit signals or set notifiers.
 */
bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& bytesWritten)
{
    // Must be locked
    bytesWritten = 0;
    while (maxSize > 0) {
        int result = ::write(d->portHandle, data, maxSize);
        if (result == -1) {
            if (errno == EAGAIN)
                return true; // Need to wait
            setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName));
            bytesWritten = -1;
            return false;
        } else {
            if (result == 0)
                qWarning("Zero bytes written to port!");
            bytesWritten += result;
            maxSize -= result;
            data += result;
        }
    }
    return false; // If we reach here we've successfully written all the data without blocking
}

/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written.
 * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than
 * attempting to drain the whole queue.
 * Doesn't modify notifier.
 */
bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags)
{
    while (pendingWrites.count() > 0) {
        // Try writing everything we've got, until we hit EAGAIN
        const QByteArray& data = pendingWrites[0];
        qint64 bytesWritten;
        bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten);
        if (needToWait) {
            if (bytesWritten > 0) {
                // We wrote some of the data, update the pending queue
                QByteArray remainder = data.mid(bytesWritten);
                pendingWrites.removeFirst();
                pendingWrites.insert(0, remainder);
            }
            return needToWait;
        } else {
            pendingWrites.removeFirst();
            if (flags & EmitBytesWrittenAsync) {
                emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
            } else {
                emitBytesWrittenIfNeeded(locker, bytesWritten);
            }
            if (flags & StopAfterWritingOneBuffer) return false;
            // Otherwise go round loop again
        }
    }
    return false; // no EAGAIN encountered
}

void VirtualSerialDevice::writeHasUnblocked(int fileHandle)
{
    Q_ASSERT(fileHandle == d->portHandle);
    (void)fileHandle; // Compiler shutter-upper
    d->writeUnblockedNotifier->setEnabled(false);

    QMutexLocker locker(&lock);
    bool needToWait = tryFlushPendingBuffers(locker);
    if (needToWait) d->writeUnblockedNotifier->setEnabled(true);
}

// Copy of qt_safe_select from /qt/src/corelib/kernel/qeventdispatcher_unix.cpp
// But without the timeout correction
int safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
                   const struct timeval *orig_timeout)
{
    if (!orig_timeout) {
        // no timeout -> block forever
        register int ret;
        do {
            ret = select(nfds, fdread, fdwrite, fdexcept, 0);
        } while (ret == -1 && errno == EINTR);
        return ret;
    }

    timeval timeout = *orig_timeout;

    int ret;
    forever {
        ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
        if (ret != -1 || errno != EINTR)
            return ret;
    }
}

bool VirtualSerialDevice::waitForBytesWritten(int msecs)
{
    QMutexLocker locker(&lock);
    if (pendingWrites.count() == 0) return false;

    if (QThread::currentThread() != thread()) {
        // Wait for signal from main thread
        unsigned long timeout = msecs;
        if (msecs == -1) timeout = ULONG_MAX;
        if (waiterForBytesWritten == NULL)
            waiterForBytesWritten = new QWaitCondition;
        return waiterForBytesWritten->wait(&lock, timeout);
    }

    d->writeUnblockedNotifier->setEnabled(false);
    forever {
        fd_set writeSet;
        FD_ZERO(&writeSet);
        FD_SET(d->portHandle, &writeSet);

        struct timeval timeout;
        if (msecs != -1) {
            timeout.tv_sec = msecs / 1000;
            timeout.tv_usec = (msecs % 1000) * 1000;
        }
        int ret = safe_select(d->portHandle+1, NULL, &writeSet, NULL, msecs == -1 ? NULL : &timeout);

        if (ret == 0) {
            // Timeout
            return false;
        } else if (ret < 0) {
            setErrorString(QString("Posix error %1 returned from select in waitForBytesWritten").arg(errno));
            return false;
        } else {
            bool needToWait = tryFlushPendingBuffers(locker, StopAfterWritingOneBuffer);
            if (needToWait) {
                // go round the select again
            } else {
                return true;
            }
        }
    }
}

void VirtualSerialDevice::flush()
{
    while (waitForBytesWritten(-1)) { /* loop */ }
    tcflush(d->portHandle, TCIOFLUSH);
}

bool VirtualSerialDevice::waitForReadyRead(int msecs)
{
    return QIODevice::waitForReadyRead(msecs); //TODO
}

} // namespace SymbianUtils
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "itkOptimizerParameters.h"
#include "itkIntTypes.h"
#include "itkTestingMacros.h"

using namespace itk;

template< typename TValueType >
bool runTestByType()
{
  bool passed = true;

  OptimizerParameters<TValueType> params;
  params.SetSize(10);
  params.Fill(1.23);
  std::cout << "GetSize: " << params.GetSize() << std::endl;

  /* Test different ctors */

  //Construct by size
  SizeValueType dim = 20;
  OptimizerParameters<TValueType> paramsSize(dim);
  if( paramsSize.GetSize() != dim )
    {
    std::cerr << "Constructor with dimension failed. Expected size of "
              << dim << ", but got " << paramsSize.GetSize() << "." << std::endl;
    passed = false;
    }

  //Copy constructor
  {
  OptimizerParameters<TValueType> paramsCopy( params );
  for( SizeValueType i=0; i < params.GetSize(); i++ )
    {
    if( params[i] != paramsCopy[i] )
      {
      std::cerr << "Copy constructor failed. " << std::endl;
      passed = false;
      }
    }
  }

  //Constructor from array
  Array<TValueType> array(dim);
  for( SizeValueType i=0; i<dim; i++ )
    { array[i]=i*3.19; }
  {
  OptimizerParameters<TValueType> paramsCopy( array );
  for( SizeValueType i=0; i < params.GetSize(); i++ )
    {
    if( array[i] != paramsCopy[i] )
      {
      std::cerr << "Constructor from Array failed. " << std::endl;
      passed = false;
      }
    }
  }

  /* Test assignment operators from different types */

  //Assign from Array
  OptimizerParameters<TValueType> paramsArray;
  paramsArray = array;
  for( SizeValueType i=0; i < array.GetSize(); i++ )
    {
    if( paramsArray[i] != array[i] )
      {
      std::cerr << "Copy from Array via assignment failed. " << std::endl;
      passed = false;
      }
    }

  //Assign from VnlVector
  vnl_vector<TValueType> vector(dim);
  for( SizeValueType i=0; i<dim; i++ )
    { vector[i]=i*0.123; }
  {
  OptimizerParameters<TValueType> paramsVnl;
  paramsVnl = vector;
  for( SizeValueType i=0; i < paramsVnl.GetSize(); i++ )
    {
    if( vector[i] != paramsVnl[i] )
      {
      std::cerr << "Assignment from VnlVector failed. " << std::endl;
      passed = false;
      }
    }
  }

  /* Test MoveDataPointer to point to different memory block */
  TValueType  block[10] = {10,9,8,7,6,5,4,3,2,1};
  params.MoveDataPointer( block );
  for( int i=0; i < 10; i++)
    {
    if( params[i] != 10-i )
      {
      std::cerr << "Failed reading memory after MoveDataPointer." << std::endl
                << "Expected: " << 10-i << ", got: " << params[i] << std::endl;
      passed = false;
      }
    }

  /* Test SetParametersObject. Should throw exception with default helper. */
  typename LightObject::Pointer dummyObj = LightObject::New();
  TRY_EXPECT_EXCEPTION( params.SetParametersObject( dummyObj.GetPointer() ) );

  /* Test with null helper and expect exception */
  params.SetHelper( NULL );
  TRY_EXPECT_EXCEPTION( params.MoveDataPointer( block ) );
  TRY_EXPECT_EXCEPTION( params.SetParametersObject( dummyObj.GetPointer() ) );

  /* Test copy operator */
  OptimizerParameters<TValueType> params1(4);
  OptimizerParameters<TValueType> params2(4);
  params1.Fill(1.23);
  params2 = params1;
  for( SizeValueType i=0; i < params1.GetSize(); i++ )
    {
    if( params1[i] != params2[i] )
      {
      std::cerr << "Copy operator failed:" << std::endl
              << "params1 " << params1 << std::endl
              << "params2 " << params2 << std::endl;
      passed = false;
      break;
      }
    }

  /* Exercise set helper */
  typedef typename OptimizerParameters<TValueType>::OptimizerParametersHelperType HelperType;
  HelperType * helper = new HelperType;
  params1.SetHelper( helper );

  return passed;
}

int itkOptimizerParametersTest(int, char *[])
{
  bool passed = true;

  /* Test double type */
  if( runTestByType<double>() == false )
    {
    passed = false;
    }
  /* Test float type */
  if( runTestByType<float>() == false )
    {
    passed = false;
    }

  return passed ? EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>COMP: Tests should not have "using namespace itk".<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "itkOptimizerParameters.h"
#include "itkIntTypes.h"
#include "itkTestingMacros.h"

template< typename TValueType >
bool runTestByType()
{
  bool passed = true;

  itk::OptimizerParameters<TValueType> params;
  params.SetSize(10);
  params.Fill(1.23);
  std::cout << "GetSize: " << params.GetSize() << std::endl;

  /* Test different ctors */

  //Construct by size
  itk::SizeValueType dim = 20;
  itk::OptimizerParameters<TValueType> paramsSize(dim);
  if( paramsSize.GetSize() != dim )
    {
    std::cerr << "Constructor with dimension failed. Expected size of "
              << dim << ", but got " << paramsSize.GetSize() << "." << std::endl;
    passed = false;
    }

  //Copy constructor
  {
  itk::OptimizerParameters<TValueType> paramsCopy( params );
  for( itk::SizeValueType i=0; i < params.GetSize(); i++ )
    {
    if( params[i] != paramsCopy[i] )
      {
      std::cerr << "Copy constructor failed. " << std::endl;
      passed = false;
      }
    }
  }

  //Constructor from array
  itk::Array<TValueType> array(dim);
  for( itk::SizeValueType i=0; i<dim; i++ )
    { array[i]=i*3.19; }
  {
  itk::OptimizerParameters<TValueType> paramsCopy( array );
  for( itk::SizeValueType i=0; i < params.GetSize(); i++ )
    {
    if( array[i] != paramsCopy[i] )
      {
      std::cerr << "Constructor from Array failed. " << std::endl;
      passed = false;
      }
    }
  }

  /* Test assignment operators from different types */

  //Assign from Array
  itk::OptimizerParameters<TValueType> paramsArray;
  paramsArray = array;
  for( itk::SizeValueType i=0; i < array.GetSize(); i++ )
    {
    if( paramsArray[i] != array[i] )
      {
      std::cerr << "Copy from Array via assignment failed. " << std::endl;
      passed = false;
      }
    }

  //Assign from VnlVector
  vnl_vector<TValueType> vector(dim);
  for( itk::SizeValueType i=0; i<dim; i++ )
    { vector[i]=i*0.123; }
  {
  itk::OptimizerParameters<TValueType> paramsVnl;
  paramsVnl = vector;
  for( itk::SizeValueType i=0; i < paramsVnl.GetSize(); i++ )
    {
    if( vector[i] != paramsVnl[i] )
      {
      std::cerr << "Assignment from VnlVector failed. " << std::endl;
      passed = false;
      }
    }
  }

  /* Test MoveDataPointer to point to different memory block */
  TValueType  block[10] = {10,9,8,7,6,5,4,3,2,1};
  params.MoveDataPointer( block );
  for( int i=0; i < 10; i++)
    {
    if( params[i] != 10-i )
      {
      std::cerr << "Failed reading memory after MoveDataPointer." << std::endl
                << "Expected: " << 10-i << ", got: " << params[i] << std::endl;
      passed = false;
      }
    }

  /* Test SetParametersObject. Should throw exception with default helper. */
  typename itk::LightObject::Pointer dummyObj = itk::LightObject::New();
  TRY_EXPECT_EXCEPTION( params.SetParametersObject( dummyObj.GetPointer() ) );

  /* Test with null helper and expect exception */
  params.SetHelper( NULL );
  TRY_EXPECT_EXCEPTION( params.MoveDataPointer( block ) );
  TRY_EXPECT_EXCEPTION( params.SetParametersObject( dummyObj.GetPointer() ) );

  /* Test copy operator */
  itk::OptimizerParameters<TValueType> params1(4);
  itk::OptimizerParameters<TValueType> params2(4);
  params1.Fill(1.23);
  params2 = params1;
  for( itk::SizeValueType i=0; i < params1.GetSize(); i++ )
    {
    if( params1[i] != params2[i] )
      {
      std::cerr << "Copy operator failed:" << std::endl
              << "params1 " << params1 << std::endl
              << "params2 " << params2 << std::endl;
      passed = false;
      break;
      }
    }

  /* Exercise set helper */
  typedef typename itk::OptimizerParameters<TValueType>::OptimizerParametersHelperType HelperType;
  HelperType * helper = new HelperType;
  params1.SetHelper( helper );

  return passed;
}

int itkOptimizerParametersTest(int, char *[])
{
  bool passed = true;

  /* Test double type */
  if( runTestByType<double>() == false )
    {
    passed = false;
    }
  /* Test float type */
  if( runTestByType<float>() == false )
    {
    passed = false;
    }

  return passed ? EXIT_SUCCESS : EXIT_FAILURE;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef otbPointSetExtractROI_hxx
#define otbPointSetExtractROI_hxx

#include "otbPointSetExtractROI.h"
#include "itkMacro.h"

namespace otb
{

/**
 *
 */
template <class TInputPointSet, class TOutputPointSet>
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::PointSetExtractROI()
{
}

/**
 *
 */
template <class TInputPointSet, class TOutputPointSet>
void
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
  Superclass::PrintSelf(os, indent);

}

/**
 * This method causes the filter to generate its output.
 */
template <class TInputPointSet, class TOutputPointSet>
void
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::GenerateData(void)
{
  typedef typename TInputPointSet::PointsContainer  InputPointsContainer;
  typedef typename TInputPointSet::PointsContainerPointer  InputPointsContainerPointer;
  typedef typename TOutputPointSet::PointsContainerPointer OutputPointsContainerPointer;

  typedef typename TInputPointSet::PointDataContainerPointer  InputPointDataContainerPointer;
  typedef typename TOutputPointSet::PointDataContainerPointer OutputPointDataContainerPointer;

  InputPointSetPointer  inputPointSet      =  this->GetInput();
  OutputPointSetPointer outputPointSet     =  this->GetOutput();

  if (!inputPointSet)
    {
    itkExceptionMacro(<< "Missing Input PointSet");
    }

  if (!outputPointSet)
    {
    itkExceptionMacro(<< "Missing Output PointSet");
    }

  outputPointSet->SetBufferedRegion(outputPointSet->GetRequestedRegion());  //TODO update outputRegion

  InputPointsContainerPointer     inPoints  = inputPointSet->GetPoints();
  InputPointDataContainerPointer  inData    = inputPointSet->GetPointData();
  OutputPointsContainerPointer    outPoints = outputPointSet->GetPoints();
  OutputPointDataContainerPointer outData = outputPointSet->GetPointData();

  typename InputPointsContainer::ConstIterator    inputPoint  = inPoints->Begin();

  // Commented cause using iterator on the pointSetData crash
  // Use a direct access to pointSet Data instead to avoid segfault
  //typename InputPointDataContainer::ConstIterator inputData = inData->Begin();
  //if (inData.IsNotNull())
  //  {
  //    inputData = inData->Begin();
  //  }

  while (inputPoint != inPoints->End())
    {
    typename InputPointsContainer::Element point = inputPoint.Value();

    if ((((point[0] >= m_StartX) && (point[0] < m_StartX + m_SizeX))
         || ((point[0] <= m_StartX) && (point[0] > m_StartX + m_SizeX))) //cover the case when size<0
        && (((point[1] >= m_StartY) && (point[1] < m_StartY + m_SizeY))
            || ((point[1] <= m_StartY) && (point[1] > m_StartY + m_SizeY))))
      {
      // Add the point
      outPoints->push_back(point);
      // Get & Add the data
      typename InputPointSetType::PixelType  data;
      inputPointSet->GetPointData(inputPoint.Index(), &data);
      outData->push_back(data/*inputData.Value()*/);
      }

    ++inputPoint;
    //++inputData;
    }
}

} // end namespace otb

#endif
<commit_msg>BUG: fix unitialized member variable<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef otbPointSetExtractROI_hxx
#define otbPointSetExtractROI_hxx

#include "otbPointSetExtractROI.h"
#include "itkMacro.h"

namespace otb
{

/**
 *
 */
template <class TInputPointSet, class TOutputPointSet>
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::PointSetExtractROI() : m_SizeX(0), m_StartY(0), m_SizeX(0), m_SizeY(0)
{
}

/**
 *
 */
template <class TInputPointSet, class TOutputPointSet>
void
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
  Superclass::PrintSelf(os, indent);

}

/**
 * This method causes the filter to generate its output.
 */
template <class TInputPointSet, class TOutputPointSet>
void
PointSetExtractROI<TInputPointSet, TOutputPointSet>
::GenerateData(void)
{
  typedef typename TInputPointSet::PointsContainer  InputPointsContainer;
  typedef typename TInputPointSet::PointsContainerPointer  InputPointsContainerPointer;
  typedef typename TOutputPointSet::PointsContainerPointer OutputPointsContainerPointer;

  typedef typename TInputPointSet::PointDataContainerPointer  InputPointDataContainerPointer;
  typedef typename TOutputPointSet::PointDataContainerPointer OutputPointDataContainerPointer;

  InputPointSetPointer  inputPointSet      =  this->GetInput();
  OutputPointSetPointer outputPointSet     =  this->GetOutput();

  if (!inputPointSet)
    {
    itkExceptionMacro(<< "Missing Input PointSet");
    }

  if (!outputPointSet)
    {
    itkExceptionMacro(<< "Missing Output PointSet");
    }

  outputPointSet->SetBufferedRegion(outputPointSet->GetRequestedRegion());  //TODO update outputRegion

  InputPointsContainerPointer     inPoints  = inputPointSet->GetPoints();
  InputPointDataContainerPointer  inData    = inputPointSet->GetPointData();
  OutputPointsContainerPointer    outPoints = outputPointSet->GetPoints();
  OutputPointDataContainerPointer outData = outputPointSet->GetPointData();

  typename InputPointsContainer::ConstIterator    inputPoint  = inPoints->Begin();

  // Commented cause using iterator on the pointSetData crash
  // Use a direct access to pointSet Data instead to avoid segfault
  //typename InputPointDataContainer::ConstIterator inputData = inData->Begin();
  //if (inData.IsNotNull())
  //  {
  //    inputData = inData->Begin();
  //  }

  while (inputPoint != inPoints->End())
    {
    typename InputPointsContainer::Element point = inputPoint.Value();

    if ((((point[0] >= m_StartX) && (point[0] < m_StartX + m_SizeX))
         || ((point[0] <= m_StartX) && (point[0] > m_StartX + m_SizeX))) //cover the case when size<0
        && (((point[1] >= m_StartY) && (point[1] < m_StartY + m_SizeY))
            || ((point[1] <= m_StartY) && (point[1] > m_StartY + m_SizeY))))
      {
      // Add the point
      outPoints->push_back(point);
      // Get & Add the data
      typename InputPointSetType::PixelType  data;
      inputPointSet->GetPointData(inputPoint.Index(), &data);
      outData->push_back(data/*inputData.Value()*/);
      }

    ++inputPoint;
    //++inputData;
    }
}

} // end namespace otb

#endif
<|endoftext|>


<commit_before>/*=========================================================================

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 "mitkMovieGeneratorOpenCV.h"
//#include <GL/gl.h>
#include "mitkgl.h"
#include <iostream>

mitk::MovieGeneratorOpenCV::MovieGeneratorOpenCV()
{
  m_initialized = false;
  m_aviWriter   = NULL;
  m_dwRate = 20;

  m_FourCCCodec = NULL;
  m_RemoveColouredFrame = true;
}

void mitk::MovieGeneratorOpenCV::SetFileName( const char *fileName )
{

  m_sFile = fileName;
}

void mitk::MovieGeneratorOpenCV::SetFrameRate(int rate)
{
  m_dwRate = rate;
}

void mitk::MovieGeneratorOpenCV::SetRemoveColouredFrame(bool RemoveColouredFrame)
{
  m_RemoveColouredFrame = RemoveColouredFrame;
}

bool mitk::MovieGeneratorOpenCV::InitGenerator()
{
  m_width = m_renderer->GetRenderWindow()->GetSize()[0];  // changed from glGetIntegerv( GL_VIEWPORT, viewport );
  m_height = m_renderer->GetRenderWindow()->GetSize()[1]; // due to sometimes strange dimensions

  if(m_RemoveColouredFrame)
  {
    m_width  -= 10;  //remove colored boarders around renderwindows
    m_height -= 10;
  }

  m_width -= m_width % 4; // some video codecs have prerequisites to the image dimensions
  m_height -= m_height % 4;

  m_currentFrame = cvCreateImage(cvSize(m_width,m_height),8,3); // creating image with widget size, 8 bit per pixel and 3 channel r,g,b
  m_currentFrame->origin = 1; // avoid building a video with bottom up

  /*
  m_sFile = Name of the output video file.
  CV_FOURCC = 4-character code of codec used to compress the frames. For example, CV_FOURCC('P','I','M','1') is MPEG-1 codec,
  CV_FOURCC('M','J','P','G') is motion-jpeg codec etc.
   CV_FOURCC('P','I','M','1')    = MPEG-1 codec
  CV_FOURCC('M','J','P','G')    = motion-jpeg codec (does not work well)
  CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
  CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
  CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
  CV_FOURCC('U', '2', '6', '3') = H263 codec
  CV_FOURCC('I', '2', '6', '3') = H263I codec
  CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

  List of FOURCC codes is available at http://msdn2.microsoft.com/en-us/library/ms867195.aspx

  Under Win32 it is possible to pass -1 in order to choose compression
  method and additional compression parameters from dialog.
  m_dwRate = Framerate of the created video stream.
  frame_size Size of video frames. InitGenerator
  1 = If it is not zero, the encoder will expect and encode color frames, otherwise it will work with grayscale frames
  (the flag is currently supported on Windows only).*/

  if(m_FourCCCodec != NULL)
  {
    #ifdef WIN32
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC(m_FourCCCodec[0],m_FourCCCodec[1],m_FourCCCodec[2],
                                        m_FourCCCodec[3]),m_dwRate,cvSize(m_width,m_height),1); //initializing video writer
    #else
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC(m_FourCCCodec[0],m_FourCCCodec[1],m_FourCCCodec[2],
                                        m_FourCCCodec[3]),m_dwRate,cvSize(m_width,m_height)); //initializing video writer
    #endif
  }
  else
  {
    #ifdef WIN32
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),-1,m_dwRate,cvSize(m_width,m_height),1); //initializing video writer
    #else
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC('X','V','I','D'),m_dwRate,cvSize(m_width,m_height)); //initializing video writer
    #endif
  }

  if(!m_aviWriter)
  {
    std::cout << "errors initializing video writer...correct video file path? on linux: ffmpeg must be included in OpenCV.";
    return false;
  }

  return true;
}

bool mitk::MovieGeneratorOpenCV::AddFrame( void *data )
{
  //cvSetImageData(m_currentFrame,data,m_width*3);
  memcpy(m_currentFrame->imageData,data,m_width*m_height*3);
  cvWriteFrame(m_aviWriter,m_currentFrame);
  return true;
}

bool mitk::MovieGeneratorOpenCV::TerminateGenerator()
{
  if (m_aviWriter)
  {
    cvReleaseVideoWriter(&m_aviWriter);
  }
  return true;
}
<commit_msg>COMP: fixed mitkGL.h path bug<commit_after>/*=========================================================================

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 "mitkMovieGeneratorOpenCV.h"
//#include <GL/gl.h>
#include "mitkGL.h"
#include <iostream>

mitk::MovieGeneratorOpenCV::MovieGeneratorOpenCV()
{
  m_initialized = false;
  m_aviWriter   = NULL;
  m_dwRate = 20;

  m_FourCCCodec = NULL;
  m_RemoveColouredFrame = true;
}

void mitk::MovieGeneratorOpenCV::SetFileName( const char *fileName )
{

  m_sFile = fileName;
}

void mitk::MovieGeneratorOpenCV::SetFrameRate(int rate)
{
  m_dwRate = rate;
}

void mitk::MovieGeneratorOpenCV::SetRemoveColouredFrame(bool RemoveColouredFrame)
{
  m_RemoveColouredFrame = RemoveColouredFrame;
}

bool mitk::MovieGeneratorOpenCV::InitGenerator()
{
  m_width = m_renderer->GetRenderWindow()->GetSize()[0];  // changed from glGetIntegerv( GL_VIEWPORT, viewport );
  m_height = m_renderer->GetRenderWindow()->GetSize()[1]; // due to sometimes strange dimensions

  if(m_RemoveColouredFrame)
  {
    m_width  -= 10;  //remove colored boarders around renderwindows
    m_height -= 10;
  }

  m_width -= m_width % 4; // some video codecs have prerequisites to the image dimensions
  m_height -= m_height % 4;

  m_currentFrame = cvCreateImage(cvSize(m_width,m_height),8,3); // creating image with widget size, 8 bit per pixel and 3 channel r,g,b
  m_currentFrame->origin = 1; // avoid building a video with bottom up

  /*
  m_sFile = Name of the output video file.
  CV_FOURCC = 4-character code of codec used to compress the frames. For example, CV_FOURCC('P','I','M','1') is MPEG-1 codec,
  CV_FOURCC('M','J','P','G') is motion-jpeg codec etc.
   CV_FOURCC('P','I','M','1')    = MPEG-1 codec
  CV_FOURCC('M','J','P','G')    = motion-jpeg codec (does not work well)
  CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
  CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
  CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
  CV_FOURCC('U', '2', '6', '3') = H263 codec
  CV_FOURCC('I', '2', '6', '3') = H263I codec
  CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

  List of FOURCC codes is available at http://msdn2.microsoft.com/en-us/library/ms867195.aspx

  Under Win32 it is possible to pass -1 in order to choose compression
  method and additional compression parameters from dialog.
  m_dwRate = Framerate of the created video stream.
  frame_size Size of video frames. InitGenerator
  1 = If it is not zero, the encoder will expect and encode color frames, otherwise it will work with grayscale frames
  (the flag is currently supported on Windows only).*/

  if(m_FourCCCodec != NULL)
  {
    #ifdef WIN32
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC(m_FourCCCodec[0],m_FourCCCodec[1],m_FourCCCodec[2],
                                        m_FourCCCodec[3]),m_dwRate,cvSize(m_width,m_height),1); //initializing video writer
    #else
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC(m_FourCCCodec[0],m_FourCCCodec[1],m_FourCCCodec[2],
                                        m_FourCCCodec[3]),m_dwRate,cvSize(m_width,m_height)); //initializing video writer
    #endif
  }
  else
  {
    #ifdef WIN32
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),-1,m_dwRate,cvSize(m_width,m_height),1); //initializing video writer
    #else
      m_aviWriter = cvCreateVideoWriter(m_sFile.c_str(),CV_FOURCC('X','V','I','D'),m_dwRate,cvSize(m_width,m_height)); //initializing video writer
    #endif
  }

  if(!m_aviWriter)
  {
    std::cout << "errors initializing video writer...correct video file path? on linux: ffmpeg must be included in OpenCV.";
    return false;
  }

  return true;
}

bool mitk::MovieGeneratorOpenCV::AddFrame( void *data )
{
  //cvSetImageData(m_currentFrame,data,m_width*3);
  memcpy(m_currentFrame->imageData,data,m_width*m_height*3);
  cvWriteFrame(m_aviWriter,m_currentFrame);
  return true;
}

bool mitk::MovieGeneratorOpenCV::TerminateGenerator()
{
  if (m_aviWriter)
  {
    cvReleaseVideoWriter(&m_aviWriter);
  }
  return true;
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY 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 "mitkSetRegionTool.h"

#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"

#include "ipSegmentation.h"

#include "mitkBaseRenderer.h"
#include "mitkImageDataItem.h"

#include "mitkOverwriteDirectedPlaneImageFilter.h"

mitk::SetRegionTool::SetRegionTool(int paintingPixelValue)
:FeedbackContourTool("PressMoveReleaseWithCTRLInversion"),
 m_PaintingPixelValue(paintingPixelValue),
 m_FillContour(false),
 m_StatusFillWholeSlice(false)
{
  // great magic numbers
  CONNECT_ACTION( 80, OnMousePressed );
  //CONNECT_ACTION( 90, OnMouseMoved );
  CONNECT_ACTION( 42, OnMouseReleased );
  CONNECT_ACTION( 49014, OnInvertLogic );

}

mitk::SetRegionTool::~SetRegionTool()
{
}

void mitk::SetRegionTool::Activated()
{
  Superclass::Activated();
}

void mitk::SetRegionTool::Deactivated()
{
  Superclass::Deactivated();
}

bool mitk::SetRegionTool::OnMousePressed (Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  m_LastEventSender = positionEvent->GetSender();
  m_LastEventSlice = m_LastEventSender->GetSlice();

  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  // 1. Get the working image
  Image::Pointer workingSlice   = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
  if ( workingSlice.IsNull() ) return false; // can't do anything without the segmentation

  // if click was outside the image, don't continue
  const Geometry3D* sliceGeometry = workingSlice->GetGeometry();
  itk::Index<2> projectedPointIn2D;
  sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), projectedPointIn2D );
  if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) )
  {
    MITK_ERROR << "point apparently not inside segmentation slice" << std::endl;
    return false; // can't use that as a seed point
  }

    // Convert to ipMITKSegmentationTYPE (because ipMITKSegmentationGetContour8N relys on that data type)
    itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
    CastToItkImage( workingSlice, correctPixelTypeImage );
    assert (correctPixelTypeImage.IsNotNull() );

  // possible bug in CastToItkImage ?
  // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in
  // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479:
  // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed
  // solution here: we overwrite it with an unity matrix
  itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
  imageDirection.SetIdentity();
  correctPixelTypeImage->SetDirection(imageDirection);

    Image::Pointer temporarySlice = Image::New();
  //  temporarySlice = ImportItkImage( correctPixelTypeImage );
    CastToMitkImage( correctPixelTypeImage, temporarySlice );

  // check index positions
  mitkIpPicDescriptor* originalPicSlice = mitkIpPicNew();
  CastToIpPicDescriptor( temporarySlice, originalPicSlice );

  int m_SeedPointMemoryOffset = projectedPointIn2D[1] * originalPicSlice->n[0] + projectedPointIn2D[0];

  if ( m_SeedPointMemoryOffset >= static_cast<int>( originalPicSlice->n[0] * originalPicSlice->n[1] ) ||
       m_SeedPointMemoryOffset < 0 )
  {
    MITK_ERROR << "Memory offset calculation if mitk::SetRegionTool has some serious flaw! Aborting.." << std::endl;
    return false;
  }

  // 2. Determine the contour that surronds the selected "piece of the image"

  // find a contour seed point
  unsigned int oneContourOffset = static_cast<unsigned int>( m_SeedPointMemoryOffset ); // safe because of earlier check if m_SeedPointMemoryOffset < 0

  /**
    * The logic of finding a starting point for the contour is the following:
    *
    *  - If the initial seed point is 0, we are either inside a hole or outside of every segmentation.
    *    We move to the right until we hit a 1, which must be part of a contour.
    *
    *  - If the initial seed point is 1, then ...
    *    we now do the same (running to the right) until we hit a 1
    *
    *  In both cases the found contour point is used to extract a contour and
    *  then a test is applied to find out if the initial seed point is contained
    *  in the contour. If this is the case, filling should be applied, otherwise
    *  nothing is done.
    */
  unsigned int size = originalPicSlice->n[0] * originalPicSlice->n[1];
/*
  unsigned int rowSize = originalPicSlice->n[0];
*/
  ipMITKSegmentationTYPE* data = static_cast<ipMITKSegmentationTYPE*>(originalPicSlice->data);

  if ( data[oneContourOffset] == 0 ) // initial seed 0
  {
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( data[oneContourOffset] > 0 ) break;
    }
  }
  else if ( data[oneContourOffset] == 1 ) // initial seed 1
  {
    unsigned int lastValidPixel = size-1; // initialization, will be changed lateron
    bool inSeg = true;    // inside segmentation?
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( ( data[oneContourOffset] == 0 ) && inSeg ) // pixel 0 and inside-flag set: this happens at the first pixel outside a filled region
      {
        inSeg = false;
        lastValidPixel = oneContourOffset - 1; // store the last pixel position inside a filled region
        break;
      }
      else // pixel 1, inside-flag doesn't matter: this happens while we are inside a filled region
      {
        inSeg = true; // first iteration lands here
      }

    }
    oneContourOffset = lastValidPixel;
  }
  else
  {
    MITK_ERROR << "Fill/Erase was never intended to work with other than binary images." << std::endl;
    m_FillContour = false;
    return false;
  }

  if (oneContourOffset == size) // nothing found until end of slice
  {
    m_FillContour = false;
    return false;
  }

  int numberOfContourPoints( 0 );
  int newBufferSize( 0 );
  //MITK_INFO << "getting contour from offset " << oneContourOffset << " ("<<oneContourOffset%originalPicSlice->n[0]<<","<<oneContourOffset/originalPicSlice->n[0]<<")"<<std::endl;
  float* contourPoints = ipMITKSegmentationGetContour8N( originalPicSlice, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc

  //MITK_INFO << "contourPoints " << contourPoints << " (N="<<numberOfContourPoints<<")"<<std::endl;
  assert(contourPoints == NULL || numberOfContourPoints > 0);

  bool cursorInsideContour = ipMITKSegmentationIsInsideContour( contourPoints, numberOfContourPoints, projectedPointIn2D[0], projectedPointIn2D[1]);

  // decide if contour should be filled or not
  m_FillContour = cursorInsideContour;

  if (m_FillContour)
  {
    // copy point from float* to mitk::Contour
    ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
    contourInImageIndexCoordinates->Initialize();
    Point3D newPoint;
    for (int index = 0; index < numberOfContourPoints; ++index)
    {
      newPoint[0] = contourPoints[ 2 * index + 0 ] - 0.5;
      newPoint[1] = contourPoints[ 2 * index + 1] - 0.5;
      newPoint[2] = 0;

      contourInImageIndexCoordinates->AddVertex(newPoint);
    }

    m_SegmentationContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );

    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  // always generate a second contour, containing the whole image (used when CTRL is pressed)
  {
    // copy point from float* to mitk::Contour
    ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
    contourInImageIndexCoordinates->Initialize();
    Point3D newPoint;
    newPoint[0] = 0; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = 0; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );

    m_WholeImageContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );

    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  free(contourPoints);

  return true;
}

bool mitk::SetRegionTool::OnMouseReleased(Action* action, const StateEvent* stateEvent)
{
  // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
  FeedbackContourTool::SetFeedbackContourVisible(false);

  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  assert( positionEvent->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());

  if (!m_FillContour && !m_StatusFillWholeSlice) return true;

  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
  if (!workingNode) return false;

  Image* image = dynamic_cast<Image*>(workingNode->GetData());
  const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
  if ( !image || !planeGeometry ) return false;

  Image::Pointer slice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image );

  if ( slice.IsNull() )
  {
      MITK_ERROR << "Unable to extract slice." << std::endl;
      return false;
  }

  ContourModel* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
  ContourModel::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, false, false ); // false: don't add 0.5 (done by FillContourInSlice)
  // false: don't constrain the contour to the image's inside
  if (projectedContour.IsNull()) return false;

  FeedbackContourTool::FillContourInSlice( projectedContour, slice, m_PaintingPixelValue );

  this->WriteBackSegmentationResult(positionEvent, slice);

  m_WholeImageContourInWorldCoordinates = NULL;
  m_SegmentationContourInWorldCoordinates = NULL;

  return true;
}

/**
  Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.
*/
bool mitk::SetRegionTool::OnInvertLogic(Action* action, const StateEvent* stateEvent)
{
  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  if (m_StatusFillWholeSlice)
  {
    // use contour extracted from image data
    if (m_SegmentationContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }
  else
  {
    // use some artificial contour
    if (m_WholeImageContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_WholeImageContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  m_StatusFillWholeSlice = !m_StatusFillWholeSlice;

  return true;
}

<commit_msg>4D contour support for SetRegionTool.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY 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 "mitkSetRegionTool.h"

#include "mitkToolManager.h"
#include "mitkOverwriteSliceImageFilter.h"

#include "ipSegmentation.h"

#include "mitkBaseRenderer.h"
#include "mitkImageDataItem.h"

#include "mitkOverwriteDirectedPlaneImageFilter.h"

mitk::SetRegionTool::SetRegionTool(int paintingPixelValue)
:FeedbackContourTool("PressMoveReleaseWithCTRLInversion"),
 m_PaintingPixelValue(paintingPixelValue),
 m_FillContour(false),
 m_StatusFillWholeSlice(false)
{
  // great magic numbers
  CONNECT_ACTION( 80, OnMousePressed );
  //CONNECT_ACTION( 90, OnMouseMoved );
  CONNECT_ACTION( 42, OnMouseReleased );
  CONNECT_ACTION( 49014, OnInvertLogic );

}

mitk::SetRegionTool::~SetRegionTool()
{
}

void mitk::SetRegionTool::Activated()
{
  Superclass::Activated();
}

void mitk::SetRegionTool::Deactivated()
{
  Superclass::Deactivated();
}

bool mitk::SetRegionTool::OnMousePressed (Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  m_LastEventSender = positionEvent->GetSender();
  m_LastEventSlice = m_LastEventSender->GetSlice();
  int timeStep = positionEvent->GetSender()->GetTimeStep();

  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  // 1. Get the working image
  Image::Pointer workingSlice   = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
  if ( workingSlice.IsNull() ) return false; // can't do anything without the segmentation

  // if click was outside the image, don't continue
  const Geometry3D* sliceGeometry = workingSlice->GetGeometry();
  itk::Index<2> projectedPointIn2D;
  sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), projectedPointIn2D );
  if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) )
  {
    MITK_ERROR << "point apparently not inside segmentation slice" << std::endl;
    return false; // can't use that as a seed point
  }

    // Convert to ipMITKSegmentationTYPE (because ipMITKSegmentationGetContour8N relys on that data type)
    itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
    CastToItkImage( workingSlice, correctPixelTypeImage );
    assert (correctPixelTypeImage.IsNotNull() );

  // possible bug in CastToItkImage ?
  // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in
  // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479:
  // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed
  // solution here: we overwrite it with an unity matrix
  itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
  imageDirection.SetIdentity();
  correctPixelTypeImage->SetDirection(imageDirection);

    Image::Pointer temporarySlice = Image::New();
  //  temporarySlice = ImportItkImage( correctPixelTypeImage );
    CastToMitkImage( correctPixelTypeImage, temporarySlice );

  // check index positions
  mitkIpPicDescriptor* originalPicSlice = mitkIpPicNew();
  CastToIpPicDescriptor( temporarySlice, originalPicSlice );

  int m_SeedPointMemoryOffset = projectedPointIn2D[1] * originalPicSlice->n[0] + projectedPointIn2D[0];

  if ( m_SeedPointMemoryOffset >= static_cast<int>( originalPicSlice->n[0] * originalPicSlice->n[1] ) ||
       m_SeedPointMemoryOffset < 0 )
  {
    MITK_ERROR << "Memory offset calculation if mitk::SetRegionTool has some serious flaw! Aborting.." << std::endl;
    return false;
  }

  // 2. Determine the contour that surronds the selected "piece of the image"

  // find a contour seed point
  unsigned int oneContourOffset = static_cast<unsigned int>( m_SeedPointMemoryOffset ); // safe because of earlier check if m_SeedPointMemoryOffset < 0

  /**
    * The logic of finding a starting point for the contour is the following:
    *
    *  - If the initial seed point is 0, we are either inside a hole or outside of every segmentation.
    *    We move to the right until we hit a 1, which must be part of a contour.
    *
    *  - If the initial seed point is 1, then ...
    *    we now do the same (running to the right) until we hit a 1
    *
    *  In both cases the found contour point is used to extract a contour and
    *  then a test is applied to find out if the initial seed point is contained
    *  in the contour. If this is the case, filling should be applied, otherwise
    *  nothing is done.
    */
  unsigned int size = originalPicSlice->n[0] * originalPicSlice->n[1];
/*
  unsigned int rowSize = originalPicSlice->n[0];
*/
  ipMITKSegmentationTYPE* data = static_cast<ipMITKSegmentationTYPE*>(originalPicSlice->data);

  if ( data[oneContourOffset] == 0 ) // initial seed 0
  {
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( data[oneContourOffset] > 0 ) break;
    }
  }
  else if ( data[oneContourOffset] == 1 ) // initial seed 1
  {
    unsigned int lastValidPixel = size-1; // initialization, will be changed lateron
    bool inSeg = true;    // inside segmentation?
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( ( data[oneContourOffset] == 0 ) && inSeg ) // pixel 0 and inside-flag set: this happens at the first pixel outside a filled region
      {
        inSeg = false;
        lastValidPixel = oneContourOffset - 1; // store the last pixel position inside a filled region
        break;
      }
      else // pixel 1, inside-flag doesn't matter: this happens while we are inside a filled region
      {
        inSeg = true; // first iteration lands here
      }

    }
    oneContourOffset = lastValidPixel;
  }
  else
  {
    MITK_ERROR << "Fill/Erase was never intended to work with other than binary images." << std::endl;
    m_FillContour = false;
    return false;
  }

  if (oneContourOffset == size) // nothing found until end of slice
  {
    m_FillContour = false;
    return false;
  }

  int numberOfContourPoints( 0 );
  int newBufferSize( 0 );
  //MITK_INFO << "getting contour from offset " << oneContourOffset << " ("<<oneContourOffset%originalPicSlice->n[0]<<","<<oneContourOffset/originalPicSlice->n[0]<<")"<<std::endl;
  float* contourPoints = ipMITKSegmentationGetContour8N( originalPicSlice, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc

  //MITK_INFO << "contourPoints " << contourPoints << " (N="<<numberOfContourPoints<<")"<<std::endl;
  assert(contourPoints == NULL || numberOfContourPoints > 0);

  bool cursorInsideContour = ipMITKSegmentationIsInsideContour( contourPoints, numberOfContourPoints, projectedPointIn2D[0], projectedPointIn2D[1]);

  // decide if contour should be filled or not
  m_FillContour = cursorInsideContour;

  if (m_FillContour)
  {
    // copy point from float* to mitk::Contour
    ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
    contourInImageIndexCoordinates->Expand(timeStep + 1);
    contourInImageIndexCoordinates->SetIsClosed(true, timeStep);
    Point3D newPoint;
    for (int index = 0; index < numberOfContourPoints; ++index)
    {
      newPoint[0] = contourPoints[ 2 * index + 0 ] - 0.5;
      newPoint[1] = contourPoints[ 2 * index + 1] - 0.5;
      newPoint[2] = 0;

      contourInImageIndexCoordinates->AddVertex(newPoint, timeStep);
    }

    m_SegmentationContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );

    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  // always generate a second contour, containing the whole image (used when CTRL is pressed)
  {
    // copy point from float* to mitk::Contour
    ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
    contourInImageIndexCoordinates->Expand(timeStep + 1);
    contourInImageIndexCoordinates->SetIsClosed(true, timeStep);
    Point3D newPoint;
    newPoint[0] = 0; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );
    newPoint[0] = 0; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint, timeStep );

    m_WholeImageContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );

    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  free(contourPoints);

  return true;
}

bool mitk::SetRegionTool::OnMouseReleased(Action* action, const StateEvent* stateEvent)
{
  // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
  FeedbackContourTool::SetFeedbackContourVisible(false);

  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  assert( positionEvent->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());

  int timeStep = positionEvent->GetSender()->GetTimeStep();

  if (!m_FillContour && !m_StatusFillWholeSlice) return true;

  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
  if (!workingNode) return false;

  Image* image = dynamic_cast<Image*>(workingNode->GetData());
  const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
  if ( !image || !planeGeometry ) return false;

  Image::Pointer slice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image );

  if ( slice.IsNull() )
  {
      MITK_ERROR << "Unable to extract slice." << std::endl;
      return false;
  }

  ContourModel* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
  ContourModel::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, false, false ); // false: don't add 0.5 (done by FillContourInSlice)
  // false: don't constrain the contour to the image's inside
  if (projectedContour.IsNull()) return false;

  FeedbackContourTool::FillContourInSlice( projectedContour, timeStep, slice, m_PaintingPixelValue );

  this->WriteBackSegmentationResult(positionEvent, slice);

  m_WholeImageContourInWorldCoordinates = NULL;
  m_SegmentationContourInWorldCoordinates = NULL;

  return true;
}

/**
  Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.
*/
bool mitk::SetRegionTool::OnInvertLogic(Action* action, const StateEvent* stateEvent)
{
  if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false;

  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  if (m_StatusFillWholeSlice)
  {
    // use contour extracted from image data
    if (m_SegmentationContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }
  else
  {
    // use some artificial contour
    if (m_WholeImageContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_WholeImageContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  m_StatusFillWholeSlice = !m_StatusFillWholeSlice;

  return true;
}

<|endoftext|>


<commit_before>/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.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.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include <iostream>
#include <iomanip>

#include "otbCommandLineArgumentParser.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbMapProjections.h"
#include "otbOrthoRectificationFilter.h"
#include "otbImage.h"
#include "otbMacro.h"

#include "itkExceptionObject.h"
#include "itkMacro.h"
#include "itkTransform.h"

#include "init/ossimInit.h"

template<typename TMapProjection>
int generic_main_carto_geo(TMapProjection* mapProjection, otb::CommandLineArgumentParseResult* parseResult)
{

  try
  {

    typedef TMapProjection MapProjectionType;

    typename MapProjectionType::InputPointType cartoPoint;
    typename MapProjectionType::OutputPointType geoPoint;

    cartoPoint[0]=parseResult->GetParameterDouble("--XCarto");
    cartoPoint[1]=parseResult->GetParameterDouble("--YCarto");

    geoPoint = mapProjection->TransformPoint(cartoPoint);

    if(!parseResult->IsOptionPresent("--OTBTesting"))
    {
      std::cout << std::setprecision(10) << "Cartographic Point  (x , y)  : (" << cartoPoint[0] << "," << cartoPoint[1] << ")" << std::endl;
      std::cout << std::setprecision(10) << "Geographic   Point (Lat,Lon) : (" << geoPoint[1] << "," <<	geoPoint[0] << ")" << std::endl;
    }
    else
    {
      std::string outputTestFileName = parseResult->GetParameterString("--OTBTesting",0);

      ofstream outputTestFile;
      outputTestFile.open(outputTestFileName.c_str());

      outputTestFile << std::setprecision(10) << "Cartographic Point  (x , y)  : (" << cartoPoint[0] << "," << cartoPoint[1] << ")" << std::endl;
      outputTestFile << std::setprecision(10) << "Geographic   Point (Lat,Lon) : (" << geoPoint[1] << "," <<	geoPoint[0] << ")" << std::endl;

      outputTestFile.close();
    }

  }
  catch( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch( ... )
  {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;

}//Fin main()

int main(int argc, char* argv[])
{
  try
  {
    ossimInit::instance()->initialize(argc, argv);

				// Parse command line parameters
    typedef otb::CommandLineArgumentParser ParserType;
    ParserType::Pointer parser = ParserType::New();

    parser->SetProgramDescription("Cartographic to geographic coordinates conversion");
    parser->AddOption("--XCarto","X cartographic value of desired point","-x");
    parser->AddOption("--YCarto","Y cartographic value of desired point","-y");
    parser->AddOptionNParams("--MapProjectionType","Type (UTM/LAMBERT/LAMBERT2/LAMBERT93/SINUS/ECKERT4/TRANSMERCATOR/MOLLWEID/SVY21) and parameters of map projection used","-mapProj");

    typedef otb::CommandLineArgumentParseResult ParserResultType;
    ParserResultType::Pointer  parseResult = ParserResultType::New();

    try
    {
      parser->ParseCommandLine(argc,argv,parseResult);
    }
    catch( itk::ExceptionObject & err )
    {
      std::string descriptionException = err.GetDescription();
      if(descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
        std::cout << "WARNING : output file pixels are converted in 'unsigned char'" << std::endl;
        return EXIT_SUCCESS;
      }
      if(descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
        return EXIT_SUCCESS;
      }
      return EXIT_FAILURE;
    }

				// Code

    std::string typeMap = parseResult->GetParameterString("--MapProjectionType",0);
    int nbParams = parseResult->GetNumberOfParameters("--MapProjectionType");
    nbParams--;

    if ((typeMap == "UTM")&&(nbParams==2))
    {
      int numZone = parseResult->GetParameterUInt("--MapProjectionType",1);
      char hemisphere = parseResult->GetParameterChar("--MapProjectionType",2);

      typedef otb::UtmInverseProjection UtmProjectionType;
      UtmProjectionType::Pointer utmProjection = UtmProjectionType::New();

      utmProjection->SetZone(numZone);
      utmProjection->SetHemisphere(hemisphere);

      return generic_main_carto_geo<UtmProjectionType>(utmProjection, parseResult);
    }
    else
    {
      std::vector<double> parameters ;

      for (int i=1; i<nbParams+1; i++)
      {
        parameters.push_back(parseResult->GetParameterDouble("--MapProjectionType",i));
      }

      if ((typeMap == "LAMBERT")&&(nbParams==4))
      {
        typedef otb::LambertConformalConicInverseProjection LambertProjectionType;
        LambertProjectionType::Pointer lambertProjection = LambertProjectionType::New();

        lambertProjection->SetParameters(parameters[0],parameters[1],parameters[2],parameters[3]);

        return generic_main_carto_geo<LambertProjectionType>(lambertProjection, parseResult);
      }
      else if ((typeMap == "LAMBERT2")&&(nbParams==0))
      {
        typedef otb::Lambert2EtenduInverseProjection Lambert2ProjectionType;
        Lambert2ProjectionType::Pointer lambert2Projection = Lambert2ProjectionType::New();

        return generic_main_carto_geo<Lambert2ProjectionType>(lambert2Projection, parseResult);
      }
      else if ((typeMap == "LAMBERT93")&&(nbParams==0))
      {
        typedef otb::Lambert93InverseProjection Lambert93ProjectionType;
        Lambert93ProjectionType::Pointer lambert93Projection = Lambert93ProjectionType::New();

        return generic_main_carto_geo<Lambert93ProjectionType>(lambert93Projection, parseResult);
      }
      else if ((typeMap == "SINUS")&&(nbParams==2))
      {
        typedef otb::SinusoidalInverseProjection SinusoidalProjectionType;
        SinusoidalProjectionType::Pointer sinusoidalProjection = SinusoidalProjectionType::New();

        sinusoidalProjection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<SinusoidalProjectionType>(sinusoidalProjection, parseResult);
      }
      else if ((typeMap == "ECKERT4")&&(nbParams==2))
      {
        typedef otb::Eckert4InverseProjection Eckert4ProjectionType;
        Eckert4ProjectionType::Pointer eckert4Projection = Eckert4ProjectionType::New();

        eckert4Projection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<Eckert4ProjectionType>(eckert4Projection, parseResult);
      }
      else if ((typeMap == "TRANSMERCATOR")&&(nbParams==3))
      {
        typedef otb::TransMercatorInverseProjection TransMercatorProjectionType;
        TransMercatorProjectionType::Pointer transMercatorProjection = TransMercatorProjectionType::New();

        transMercatorProjection->SetParameters(parameters[0],parameters[1],parameters[2]);

        return generic_main_carto_geo<TransMercatorProjectionType>(transMercatorProjection, parseResult);
      }
      else if ((typeMap == "MOLLWEID")&&(nbParams==2))
      {
        typedef otb::MollweidInverseProjection MollweidProjectionType;
        MollweidProjectionType::Pointer mollweidProjection = MollweidProjectionType::New();

        mollweidProjection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<MollweidProjectionType>(mollweidProjection, parseResult);
      }
      else if ((typeMap == "SVY21")&&(nbParams==0))
      {
        typedef otb::SVY21InverseProjection SVY21ProjectionType;
        SVY21ProjectionType::Pointer svy21Projection = SVY21ProjectionType::New();

        return generic_main_carto_geo<SVY21ProjectionType>(svy21Projection, parseResult);
      }
      else
      {
        itkGenericExceptionMacro(<< "TypeMap not recognized, choose one with (parameters) : UTM(2), LAMBERT(4), LAMBERT2(0), LAMBERT2(93), SINUS(2), ECKERT4(2), TRANSMERCATOR(3), MOLLWEID(2), SVY21(0)");
      }

    }

  }
  catch( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch( ... )
  {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

<commit_msg>STYLE: tab replaced by 2 spaces<commit_after>/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.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.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include <iostream>
#include <iomanip>

#include "otbCommandLineArgumentParser.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbMapProjections.h"
#include "otbOrthoRectificationFilter.h"
#include "otbImage.h"
#include "otbMacro.h"

#include "itkExceptionObject.h"
#include "itkMacro.h"
#include "itkTransform.h"

#include "init/ossimInit.h"

template<typename TMapProjection>
int generic_main_carto_geo(TMapProjection* mapProjection, otb::CommandLineArgumentParseResult* parseResult)
{

  try
  {

    typedef TMapProjection MapProjectionType;

    typename MapProjectionType::InputPointType cartoPoint;
    typename MapProjectionType::OutputPointType geoPoint;

    cartoPoint[0]=parseResult->GetParameterDouble("--XCarto");
    cartoPoint[1]=parseResult->GetParameterDouble("--YCarto");

    geoPoint = mapProjection->TransformPoint(cartoPoint);

    if(!parseResult->IsOptionPresent("--OTBTesting"))
    {
      std::cout << std::setprecision(10) << "Cartographic Point  (x , y)  : (" << cartoPoint[0] << "," << cartoPoint[1] << ")" << std::endl;
      std::cout << std::setprecision(10) << "Geographic   Point (Lat,Lon) : (" << geoPoint[1] << "," <<  geoPoint[0] << ")" << std::endl;
    }
    else
    {
      std::string outputTestFileName = parseResult->GetParameterString("--OTBTesting",0);

      ofstream outputTestFile;
      outputTestFile.open(outputTestFileName.c_str());

      outputTestFile << std::setprecision(10) << "Cartographic Point  (x , y)  : (" << cartoPoint[0] << "," << cartoPoint[1] << ")" << std::endl;
      outputTestFile << std::setprecision(10) << "Geographic   Point (Lat,Lon) : (" << geoPoint[1] << "," <<  geoPoint[0] << ")" << std::endl;

      outputTestFile.close();
    }

  }
  catch( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch( ... )
  {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;

}//Fin main()

int main(int argc, char* argv[])
{
  try
  {
    ossimInit::instance()->initialize(argc, argv);

        // Parse command line parameters
    typedef otb::CommandLineArgumentParser ParserType;
    ParserType::Pointer parser = ParserType::New();

    parser->SetProgramDescription("Cartographic to geographic coordinates conversion");
    parser->AddOption("--XCarto","X cartographic value of desired point","-x");
    parser->AddOption("--YCarto","Y cartographic value of desired point","-y");
    parser->AddOptionNParams("--MapProjectionType","Type (UTM/LAMBERT/LAMBERT2/LAMBERT93/SINUS/ECKERT4/TRANSMERCATOR/MOLLWEID/SVY21) and parameters of map projection used","-mapProj");

    typedef otb::CommandLineArgumentParseResult ParserResultType;
    ParserResultType::Pointer  parseResult = ParserResultType::New();

    try
    {
      parser->ParseCommandLine(argc,argv,parseResult);
    }
    catch( itk::ExceptionObject & err )
    {
      std::string descriptionException = err.GetDescription();
      if(descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
        std::cout << "WARNING : output file pixels are converted in 'unsigned char'" << std::endl;
        return EXIT_SUCCESS;
      }
      if(descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
        return EXIT_SUCCESS;
      }
      return EXIT_FAILURE;
    }

        // Code

    std::string typeMap = parseResult->GetParameterString("--MapProjectionType",0);
    int nbParams = parseResult->GetNumberOfParameters("--MapProjectionType");
    nbParams--;

    if ((typeMap == "UTM")&&(nbParams==2))
    {
      int numZone = parseResult->GetParameterUInt("--MapProjectionType",1);
      char hemisphere = parseResult->GetParameterChar("--MapProjectionType",2);

      typedef otb::UtmInverseProjection UtmProjectionType;
      UtmProjectionType::Pointer utmProjection = UtmProjectionType::New();

      utmProjection->SetZone(numZone);
      utmProjection->SetHemisphere(hemisphere);

      return generic_main_carto_geo<UtmProjectionType>(utmProjection, parseResult);
    }
    else
    {
      std::vector<double> parameters ;

      for (int i=1; i<nbParams+1; i++)
      {
        parameters.push_back(parseResult->GetParameterDouble("--MapProjectionType",i));
      }

      if ((typeMap == "LAMBERT")&&(nbParams==4))
      {
        typedef otb::LambertConformalConicInverseProjection LambertProjectionType;
        LambertProjectionType::Pointer lambertProjection = LambertProjectionType::New();

        lambertProjection->SetParameters(parameters[0],parameters[1],parameters[2],parameters[3]);

        return generic_main_carto_geo<LambertProjectionType>(lambertProjection, parseResult);
      }
      else if ((typeMap == "LAMBERT2")&&(nbParams==0))
      {
        typedef otb::Lambert2EtenduInverseProjection Lambert2ProjectionType;
        Lambert2ProjectionType::Pointer lambert2Projection = Lambert2ProjectionType::New();

        return generic_main_carto_geo<Lambert2ProjectionType>(lambert2Projection, parseResult);
      }
      else if ((typeMap == "LAMBERT93")&&(nbParams==0))
      {
        typedef otb::Lambert93InverseProjection Lambert93ProjectionType;
        Lambert93ProjectionType::Pointer lambert93Projection = Lambert93ProjectionType::New();

        return generic_main_carto_geo<Lambert93ProjectionType>(lambert93Projection, parseResult);
      }
      else if ((typeMap == "SINUS")&&(nbParams==2))
      {
        typedef otb::SinusoidalInverseProjection SinusoidalProjectionType;
        SinusoidalProjectionType::Pointer sinusoidalProjection = SinusoidalProjectionType::New();

        sinusoidalProjection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<SinusoidalProjectionType>(sinusoidalProjection, parseResult);
      }
      else if ((typeMap == "ECKERT4")&&(nbParams==2))
      {
        typedef otb::Eckert4InverseProjection Eckert4ProjectionType;
        Eckert4ProjectionType::Pointer eckert4Projection = Eckert4ProjectionType::New();

        eckert4Projection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<Eckert4ProjectionType>(eckert4Projection, parseResult);
      }
      else if ((typeMap == "TRANSMERCATOR")&&(nbParams==3))
      {
        typedef otb::TransMercatorInverseProjection TransMercatorProjectionType;
        TransMercatorProjectionType::Pointer transMercatorProjection = TransMercatorProjectionType::New();

        transMercatorProjection->SetParameters(parameters[0],parameters[1],parameters[2]);

        return generic_main_carto_geo<TransMercatorProjectionType>(transMercatorProjection, parseResult);
      }
      else if ((typeMap == "MOLLWEID")&&(nbParams==2))
      {
        typedef otb::MollweidInverseProjection MollweidProjectionType;
        MollweidProjectionType::Pointer mollweidProjection = MollweidProjectionType::New();

        mollweidProjection->SetParameters(parameters[0],parameters[1]);

        return generic_main_carto_geo<MollweidProjectionType>(mollweidProjection, parseResult);
      }
      else if ((typeMap == "SVY21")&&(nbParams==0))
      {
        typedef otb::SVY21InverseProjection SVY21ProjectionType;
        SVY21ProjectionType::Pointer svy21Projection = SVY21ProjectionType::New();

        return generic_main_carto_geo<SVY21ProjectionType>(svy21Projection, parseResult);
      }
      else
      {
        itkGenericExceptionMacro(<< "TypeMap not recognized, choose one with (parameters) : UTM(2), LAMBERT(4), LAMBERT2(0), LAMBERT2(93), SINUS(2), ECKERT4(2), TRANSMERCATOR(3), MOLLWEID(2), SVY21(0)");
      }

    }

  }
  catch( itk::ExceptionObject & err )
  {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
  }
  catch( std::bad_alloc & err )
  {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
  }
  catch( ... )
  {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

<|endoftext|>