<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "puppetcreator.h"

#include <QProcess>
#include <QTemporaryDir>
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QDateTime>

#include <projectexplorer/kit.h>
#include <projectexplorer/toolchain.h>
#include <utils/environment.h>
#include <coreplugin/icore.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>

#include "puppetbuildprogressdialog.h"

#include <QtDebug>

namespace QmlDesigner {

bool PuppetCreator::m_useOnlyFallbackPuppet = !qgetenv("USE_ONLY_FALLBACK_PUPPET").isEmpty();
QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml1PuppetForKitPuppetHash;
QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml2PuppetForKitPuppetHash;

QByteArray PuppetCreator::qtHash() const
{
    if (m_kit) {
        QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
        if (currentQtVersion)
            return QCryptographicHash::hash(currentQtVersion->qmakeProperty("QT_INSTALL_DATA").toUtf8(), QCryptographicHash::Sha1).toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
    }

    return QByteArray();
}

QDateTime PuppetCreator::qtLastModified() const
{
    if (m_kit) {
        QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
        if (currentQtVersion)
            return QFileInfo(currentQtVersion->qmakeProperty("QT_INSTALL_LIBS")).lastModified();
    }

    return QDateTime();
}

PuppetCreator::PuppetCreator(ProjectExplorer::Kit *kit, const QString &qtCreatorVersion)
    : m_qtCreatorVersion(qtCreatorVersion),
      m_kit(kit),
      m_availablePuppetType(FallbackPuppet)
{
}

PuppetCreator::~PuppetCreator()
{
}

void PuppetCreator::createPuppetExecutableIfMissing(PuppetCreator::QmlPuppetVersion puppetVersion)
{
    if (puppetVersion == Qml1Puppet)
        createQml1PuppetExecutableIfMissing();
    else
        createQml2PuppetExecutableIfMissing();
}

QProcess *PuppetCreator::createPuppetProcess(PuppetCreator::QmlPuppetVersion puppetVersion, const QString &puppetMode, const QString &socketToken, QObject *handlerObject, const char *outputSlot, const char *finishSlot) const
{
    QString puppetPath;
    if (puppetVersion == Qml1Puppet)
        puppetPath = qmlpuppetPath(m_availablePuppetType);
     else
        puppetPath = qml2puppetPath(m_availablePuppetType);

    return puppetProcess(puppetPath,
                         puppetMode,
                         socketToken,
                         handlerObject,
                         outputSlot,
                         finishSlot);
}

QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
                                       const QString &puppetMode,
                                       const QString &socketToken,
                                       QObject *handlerObject,
                                       const char *outputSlot,
                                       const char *finishSlot) const
{
    QProcess *puppetProcess = new QProcess;
    puppetProcess->setObjectName(puppetMode);
    puppetProcess->setProcessEnvironment(processEnvironment());
    QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), puppetProcess, SLOT(kill()));
    QObject::connect(puppetProcess, SIGNAL(finished(int,QProcess::ExitStatus)), handlerObject, finishSlot);
    bool fowardQmlpuppetOutput = !qgetenv("FORWARD_QMLPUPPET_OUTPUT").isEmpty();
    if (fowardQmlpuppetOutput) {
        puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
        QObject::connect(puppetProcess, SIGNAL(readyRead()), handlerObject, outputSlot);
    }
    puppetProcess->start(puppetPath, QStringList() << socketToken << puppetMode << "-graphicssystem raster");

    return puppetProcess;
}

bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const
{
    PuppetBuildProgressDialog progressDialog;

    m_compileLog.clear();

    QTemporaryDir buildDirectory;

    bool buildSucceeded = false;

    if (qtIsSupported()) {
        if (buildDirectory.isValid()) {
            QStringList qmakeArguments;
            qmakeArguments.append(QStringLiteral("-r"));
            qmakeArguments.append(QStringLiteral("-after"));
            qmakeArguments.append(QStringLiteral("DESTDIR=") + qmlpuppetDirectory(UserSpacePuppet));
#ifndef QT_DEBUG
            qmakeArguments.append(QStringLiteral("CONFIG+=release"));
#endif
            qmakeArguments.append(qmlPuppetProjectFilePath);
            buildSucceeded = startBuildProcess(buildDirectory.path(), qmakeCommand(), qmakeArguments);
            if (buildSucceeded) {
                progressDialog.show();
                buildSucceeded = startBuildProcess(buildDirectory.path(), buildCommand(), QStringList(), &progressDialog);
                progressDialog.hide();
            }
        } else {
            buildSucceeded = true;
        }
    }

    return buildSucceeded;
}

void PuppetCreator::createQml1PuppetExecutableIfMissing()
{
    if (!m_useOnlyFallbackPuppet && m_kit) {
        if (m_qml1PuppetForKitPuppetHash.contains(m_kit->id())) {
            m_availablePuppetType = m_qml1PuppetForKitPuppetHash.value(m_kit->id());
        } else if (checkQmlpuppetIsReady()) {
            m_availablePuppetType = UserSpacePuppet;
        } else {
            bool buildSucceeded = build(qmlpuppetProjectFile());
            if (buildSucceeded)
                m_availablePuppetType = UserSpacePuppet;
            else
                m_availablePuppetType = FallbackPuppet;
        }

        m_qml1PuppetForKitPuppetHash.insert(m_kit->id(), m_availablePuppetType);

    } else {
        m_availablePuppetType = FallbackPuppet;
    }
}

void PuppetCreator::createQml2PuppetExecutableIfMissing()
{
    if (!m_useOnlyFallbackPuppet && m_kit) {
        if (m_qml2PuppetForKitPuppetHash.contains(m_kit->id())) {
            m_availablePuppetType = m_qml2PuppetForKitPuppetHash.value(m_kit->id());
        } else if (checkQml2puppetIsReady()) {
            m_availablePuppetType = UserSpacePuppet;
        } else {
            bool buildSucceeded = build(qml2puppetProjectFile());
            if (buildSucceeded)
                m_availablePuppetType = UserSpacePuppet;
            else
                m_availablePuppetType = FallbackPuppet;
        }

        m_qml2PuppetForKitPuppetHash.insert(m_kit->id(), m_availablePuppetType);

    } else {
        m_availablePuppetType = FallbackPuppet;
    }
}

QString PuppetCreator::qmlpuppetDirectory(PuppetType puppetType) const
{

    if (puppetType == UserSpacePuppet)
        return Core::ICore::userResourcePath()
                + QStringLiteral("/qmlpuppet/")
                + QCoreApplication::applicationVersion() + QStringLiteral("/")
                + qtHash();

    return qmlpuppetFallbackDirectory();
}

QString PuppetCreator::qmlpuppetFallbackDirectory() const
{
    return QCoreApplication::applicationDirPath();
}

QString PuppetCreator::qml2puppetPath(PuppetType puppetType) const
{
    return qmlpuppetDirectory(puppetType) + QStringLiteral("/qml2puppet") + QStringLiteral(QTC_HOST_EXE_SUFFIX);
}

QString PuppetCreator::qmlpuppetPath(PuppetType puppetType) const
{
    return qmlpuppetDirectory(puppetType) + QStringLiteral("/qmlpuppet") + QStringLiteral(QTC_HOST_EXE_SUFFIX);
}

QProcessEnvironment PuppetCreator::processEnvironment() const
{
    Utils::Environment environment = Utils::Environment::systemEnvironment();
    m_kit->addToEnvironment(environment);
    environment.set("QML_BAD_GUI_RENDER_LOOP", "true");
    environment.set("QML_USE_MOCKUPS", "true");
    environment.set("QML_PUPPET_MODE", "true");

    return environment.toProcessEnvironment();
}

QString PuppetCreator::buildCommand() const
{
    Utils::Environment environment = Utils::Environment::systemEnvironment();
    m_kit->addToEnvironment(environment);

    ProjectExplorer::ToolChain *toolChain = ProjectExplorer::ToolChainKitInformation::toolChain(m_kit);

    if (toolChain)
        return toolChain->makeCommand(environment);

    return QString();
}

QString PuppetCreator::qmakeCommand() const
{
    QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
    if (currentQtVersion)
        return currentQtVersion->qmakeCommand().toString();

    return QString();
}

QString PuppetCreator::compileLog() const
{
    return m_compileLog;
}

bool PuppetCreator::startBuildProcess(const QString &buildDirectoryPath,
                                      const QString &command,
                                      const QStringList &processArguments,
                                      PuppetBuildProgressDialog *progressDialog) const
{
    if (command.isEmpty())
        return false;

    QProcess process;
    process.setProcessChannelMode(QProcess::MergedChannels);
    process.setProcessEnvironment(processEnvironment());
    process.setWorkingDirectory(buildDirectoryPath);
    process.start(command, processArguments);
    process.waitForStarted();
    while (process.waitForReadyRead(-1)) {
        QByteArray newOutput = process.readAllStandardOutput();
        if (progressDialog)
            progressDialog->newBuildOutput(newOutput);

        m_compileLog.append(newOutput);
    }

    process.waitForFinished(1000);

    if (process.exitStatus() == QProcess::NormalExit || process.exitCode() == 0)
        return true;
    else
        return false;
}

QString PuppetCreator::puppetSourceDirectoryPath()
{
    return Core::ICore::resourcePath() + QStringLiteral("/qml/qmlpuppet");
}

QString PuppetCreator::qml2puppetProjectFile()
{
    return puppetSourceDirectoryPath() + QStringLiteral("/qml2puppet/qml2puppet.pro");
}

QString PuppetCreator::qmlpuppetProjectFile()
{
    return puppetSourceDirectoryPath() + QStringLiteral("/qmlpuppet/qmlpuppet.pro");
}

bool PuppetCreator::checkPuppetIsReady(const QString &puppetPath) const
{
    QFileInfo puppetFileInfo(puppetPath);

    return puppetFileInfo.exists() && puppetFileInfo.lastModified() > qtLastModified();
}

bool PuppetCreator::checkQml2puppetIsReady() const
{
    return checkPuppetIsReady(qml2puppetPath(UserSpacePuppet));
}

bool PuppetCreator::checkQmlpuppetIsReady() const
{
    return checkPuppetIsReady(qmlpuppetPath(UserSpacePuppet));
}

bool PuppetCreator::qtIsSupported() const
{
    QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);

    if (currentQtVersion
            && currentQtVersion->isValid()
            && currentQtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0)
            && (currentQtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT)
                || currentQtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT)))
        return true;

    return false;
}

bool PuppetCreator::checkPuppetVersion(const QString &qmlPuppetPath)
{

    QProcess qmlPuppetVersionProcess;
    qmlPuppetVersionProcess.start(qmlPuppetPath, QStringList() << "--version");
    qmlPuppetVersionProcess.waitForReadyRead(6000);

    QByteArray versionString = qmlPuppetVersionProcess.readAll();

    bool canConvert;
    unsigned int versionNumber = versionString.toUInt(&canConvert);

    return canConvert && versionNumber == 2;

}

} // namespace QmlDesigner
<commit_msg>QmlDesigner: Increase timeout for puppet creation<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "puppetcreator.h"

#include <QProcess>
#include <QTemporaryDir>
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QDateTime>

#include <projectexplorer/kit.h>
#include <projectexplorer/toolchain.h>
#include <utils/environment.h>
#include <coreplugin/icore.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>

#include "puppetbuildprogressdialog.h"

#include <QtDebug>

namespace QmlDesigner {

bool PuppetCreator::m_useOnlyFallbackPuppet = !qgetenv("USE_ONLY_FALLBACK_PUPPET").isEmpty();
QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml1PuppetForKitPuppetHash;
QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml2PuppetForKitPuppetHash;

QByteArray PuppetCreator::qtHash() const
{
    if (m_kit) {
        QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
        if (currentQtVersion)
            return QCryptographicHash::hash(currentQtVersion->qmakeProperty("QT_INSTALL_DATA").toUtf8(), QCryptographicHash::Sha1).toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
    }

    return QByteArray();
}

QDateTime PuppetCreator::qtLastModified() const
{
    if (m_kit) {
        QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
        if (currentQtVersion)
            return QFileInfo(currentQtVersion->qmakeProperty("QT_INSTALL_LIBS")).lastModified();
    }

    return QDateTime();
}

PuppetCreator::PuppetCreator(ProjectExplorer::Kit *kit, const QString &qtCreatorVersion)
    : m_qtCreatorVersion(qtCreatorVersion),
      m_kit(kit),
      m_availablePuppetType(FallbackPuppet)
{
}

PuppetCreator::~PuppetCreator()
{
}

void PuppetCreator::createPuppetExecutableIfMissing(PuppetCreator::QmlPuppetVersion puppetVersion)
{
    if (puppetVersion == Qml1Puppet)
        createQml1PuppetExecutableIfMissing();
    else
        createQml2PuppetExecutableIfMissing();
}

QProcess *PuppetCreator::createPuppetProcess(PuppetCreator::QmlPuppetVersion puppetVersion, const QString &puppetMode, const QString &socketToken, QObject *handlerObject, const char *outputSlot, const char *finishSlot) const
{
    QString puppetPath;
    if (puppetVersion == Qml1Puppet)
        puppetPath = qmlpuppetPath(m_availablePuppetType);
     else
        puppetPath = qml2puppetPath(m_availablePuppetType);

    return puppetProcess(puppetPath,
                         puppetMode,
                         socketToken,
                         handlerObject,
                         outputSlot,
                         finishSlot);
}

QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
                                       const QString &puppetMode,
                                       const QString &socketToken,
                                       QObject *handlerObject,
                                       const char *outputSlot,
                                       const char *finishSlot) const
{
    QProcess *puppetProcess = new QProcess;
    puppetProcess->setObjectName(puppetMode);
    puppetProcess->setProcessEnvironment(processEnvironment());
    QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), puppetProcess, SLOT(kill()));
    QObject::connect(puppetProcess, SIGNAL(finished(int,QProcess::ExitStatus)), handlerObject, finishSlot);
    bool fowardQmlpuppetOutput = !qgetenv("FORWARD_QMLPUPPET_OUTPUT").isEmpty();
    if (fowardQmlpuppetOutput) {
        puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
        QObject::connect(puppetProcess, SIGNAL(readyRead()), handlerObject, outputSlot);
    }
    puppetProcess->start(puppetPath, QStringList() << socketToken << puppetMode << "-graphicssystem raster");

    return puppetProcess;
}

bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const
{
    PuppetBuildProgressDialog progressDialog;

    m_compileLog.clear();

    QTemporaryDir buildDirectory;

    bool buildSucceeded = false;

    if (qtIsSupported()) {
        if (buildDirectory.isValid()) {
            QStringList qmakeArguments;
            qmakeArguments.append(QStringLiteral("-r"));
            qmakeArguments.append(QStringLiteral("-after"));
            qmakeArguments.append(QStringLiteral("DESTDIR=") + qmlpuppetDirectory(UserSpacePuppet));
#ifndef QT_DEBUG
            qmakeArguments.append(QStringLiteral("CONFIG+=release"));
#endif
            qmakeArguments.append(qmlPuppetProjectFilePath);
            buildSucceeded = startBuildProcess(buildDirectory.path(), qmakeCommand(), qmakeArguments);
            if (buildSucceeded) {
                progressDialog.show();
                buildSucceeded = startBuildProcess(buildDirectory.path(), buildCommand(), QStringList(), &progressDialog);
                progressDialog.hide();
            }
        } else {
            buildSucceeded = true;
        }
    }

    return buildSucceeded;
}

void PuppetCreator::createQml1PuppetExecutableIfMissing()
{
    if (!m_useOnlyFallbackPuppet && m_kit) {
        if (m_qml1PuppetForKitPuppetHash.contains(m_kit->id())) {
            m_availablePuppetType = m_qml1PuppetForKitPuppetHash.value(m_kit->id());
        } else if (checkQmlpuppetIsReady()) {
            m_availablePuppetType = UserSpacePuppet;
        } else {
            bool buildSucceeded = build(qmlpuppetProjectFile());
            if (buildSucceeded)
                m_availablePuppetType = UserSpacePuppet;
            else
                m_availablePuppetType = FallbackPuppet;
        }

        m_qml1PuppetForKitPuppetHash.insert(m_kit->id(), m_availablePuppetType);

    } else {
        m_availablePuppetType = FallbackPuppet;
    }
}

void PuppetCreator::createQml2PuppetExecutableIfMissing()
{
    if (!m_useOnlyFallbackPuppet && m_kit) {
        if (m_qml2PuppetForKitPuppetHash.contains(m_kit->id())) {
            m_availablePuppetType = m_qml2PuppetForKitPuppetHash.value(m_kit->id());
        } else if (checkQml2puppetIsReady()) {
            m_availablePuppetType = UserSpacePuppet;
        } else {
            bool buildSucceeded = build(qml2puppetProjectFile());
            if (buildSucceeded)
                m_availablePuppetType = UserSpacePuppet;
            else
                m_availablePuppetType = FallbackPuppet;
        }

        m_qml2PuppetForKitPuppetHash.insert(m_kit->id(), m_availablePuppetType);

    } else {
        m_availablePuppetType = FallbackPuppet;
    }
}

QString PuppetCreator::qmlpuppetDirectory(PuppetType puppetType) const
{

    if (puppetType == UserSpacePuppet)
        return Core::ICore::userResourcePath()
                + QStringLiteral("/qmlpuppet/")
                + QCoreApplication::applicationVersion() + QStringLiteral("/")
                + qtHash();

    return qmlpuppetFallbackDirectory();
}

QString PuppetCreator::qmlpuppetFallbackDirectory() const
{
    return QCoreApplication::applicationDirPath();
}

QString PuppetCreator::qml2puppetPath(PuppetType puppetType) const
{
    return qmlpuppetDirectory(puppetType) + QStringLiteral("/qml2puppet") + QStringLiteral(QTC_HOST_EXE_SUFFIX);
}

QString PuppetCreator::qmlpuppetPath(PuppetType puppetType) const
{
    return qmlpuppetDirectory(puppetType) + QStringLiteral("/qmlpuppet") + QStringLiteral(QTC_HOST_EXE_SUFFIX);
}

QProcessEnvironment PuppetCreator::processEnvironment() const
{
    Utils::Environment environment = Utils::Environment::systemEnvironment();
    m_kit->addToEnvironment(environment);
    environment.set("QML_BAD_GUI_RENDER_LOOP", "true");
    environment.set("QML_USE_MOCKUPS", "true");
    environment.set("QML_PUPPET_MODE", "true");

    return environment.toProcessEnvironment();
}

QString PuppetCreator::buildCommand() const
{
    Utils::Environment environment = Utils::Environment::systemEnvironment();
    m_kit->addToEnvironment(environment);

    ProjectExplorer::ToolChain *toolChain = ProjectExplorer::ToolChainKitInformation::toolChain(m_kit);

    if (toolChain)
        return toolChain->makeCommand(environment);

    return QString();
}

QString PuppetCreator::qmakeCommand() const
{
    QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);
    if (currentQtVersion)
        return currentQtVersion->qmakeCommand().toString();

    return QString();
}

QString PuppetCreator::compileLog() const
{
    return m_compileLog;
}

bool PuppetCreator::startBuildProcess(const QString &buildDirectoryPath,
                                      const QString &command,
                                      const QStringList &processArguments,
                                      PuppetBuildProgressDialog *progressDialog) const
{
    if (command.isEmpty())
        return false;

    QProcess process;
    process.setProcessChannelMode(QProcess::MergedChannels);
    process.setProcessEnvironment(processEnvironment());
    process.setWorkingDirectory(buildDirectoryPath);
    process.start(command, processArguments);
    process.waitForStarted();
    while (process.waitForReadyRead(-1)) {
        QByteArray newOutput = process.readAllStandardOutput();
        if (progressDialog)
            progressDialog->newBuildOutput(newOutput);

        m_compileLog.append(newOutput);
    }

    process.waitForFinished();

    if (process.exitStatus() == QProcess::NormalExit || process.exitCode() == 0)
        return true;
    else
        return false;
}

QString PuppetCreator::puppetSourceDirectoryPath()
{
    return Core::ICore::resourcePath() + QStringLiteral("/qml/qmlpuppet");
}

QString PuppetCreator::qml2puppetProjectFile()
{
    return puppetSourceDirectoryPath() + QStringLiteral("/qml2puppet/qml2puppet.pro");
}

QString PuppetCreator::qmlpuppetProjectFile()
{
    return puppetSourceDirectoryPath() + QStringLiteral("/qmlpuppet/qmlpuppet.pro");
}

bool PuppetCreator::checkPuppetIsReady(const QString &puppetPath) const
{
    QFileInfo puppetFileInfo(puppetPath);

    return puppetFileInfo.exists() && puppetFileInfo.lastModified() > qtLastModified();
}

bool PuppetCreator::checkQml2puppetIsReady() const
{
    return checkPuppetIsReady(qml2puppetPath(UserSpacePuppet));
}

bool PuppetCreator::checkQmlpuppetIsReady() const
{
    return checkPuppetIsReady(qmlpuppetPath(UserSpacePuppet));
}

bool PuppetCreator::qtIsSupported() const
{
    QtSupport::BaseQtVersion *currentQtVersion = QtSupport::QtKitInformation::qtVersion(m_kit);

    if (currentQtVersion
            && currentQtVersion->isValid()
            && currentQtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0)
            && (currentQtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT)
                || currentQtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT)))
        return true;

    return false;
}

bool PuppetCreator::checkPuppetVersion(const QString &qmlPuppetPath)
{

    QProcess qmlPuppetVersionProcess;
    qmlPuppetVersionProcess.start(qmlPuppetPath, QStringList() << "--version");
    qmlPuppetVersionProcess.waitForReadyRead(6000);

    QByteArray versionString = qmlPuppetVersionProcess.readAll();

    bool canConvert;
    unsigned int versionNumber = versionString.toUInt(&canConvert);

    return canConvert && versionNumber == 2;

}

} // namespace QmlDesigner
<|endoftext|>


<commit_before>/****************************************************************************
 **
 ** Copyright (C) 2014 Jolla Ltd.
 ** Contact: Chris Adams <chris.adams@jolla.com>
 **
 ****************************************************************************/

#include "twitternotificationsplugin.h"
#include "twittermentiontimelinesyncadaptor.h"
#include "socialnetworksyncadaptor.h"

extern "C" TwitterNotificationsPlugin* createPlugin(const QString& pluginName,
                                       const Buteo::SyncProfile& profile,
                                       Buteo::PluginCbInterface *callbackInterface)
{
    return new TwitterNotificationsPlugin(pluginName, profile, callbackInterface);
}

extern "C" void destroyPlugin(TwitterNotificationsPlugin* plugin)
{
    delete plugin;
}

TwitterNotificationsPlugin::TwitterNotificationsPlugin(const QString& pluginName,
                             const Buteo::SyncProfile& profile,
                             Buteo::PluginCbInterface *callbackInterface)
    : SocialdButeoPlugin(pluginName, profile, callbackInterface,
                         QStringLiteral("twitter"),
                         SocialNetworkSyncAdaptor::dataTypeName(SocialNetworkSyncAdaptor::Notifications))
{
}

TwitterNotificationsPlugin::~TwitterNotificationsPlugin()
{
}

SocialNetworkSyncAdaptor *TwitterNotificationsPlugin::createSocialNetworkSyncAdaptor()
{
    return new TwitterMentionTimelineSyncAdaptor(this);
}
<commit_msg>[sociald] Load translator for Twitter notifications. Contributes to JB#19139<commit_after>/****************************************************************************
 **
 ** Copyright (C) 2014 Jolla Ltd.
 ** Contact: Chris Adams <chris.adams@jolla.com>
 **
 ****************************************************************************/

#include "twitternotificationsplugin.h"
#include "twittermentiontimelinesyncadaptor.h"
#include "socialnetworksyncadaptor.h"

#include <QTranslator>
#include <QCoreApplication>

extern "C" TwitterNotificationsPlugin* createPlugin(const QString& pluginName,
                                       const Buteo::SyncProfile& profile,
                                       Buteo::PluginCbInterface *callbackInterface)
{
    return new TwitterNotificationsPlugin(pluginName, profile, callbackInterface);
}

extern "C" void destroyPlugin(TwitterNotificationsPlugin* plugin)
{
    delete plugin;
}

TwitterNotificationsPlugin::TwitterNotificationsPlugin(const QString& pluginName,
                             const Buteo::SyncProfile& profile,
                             Buteo::PluginCbInterface *callbackInterface)
    : SocialdButeoPlugin(pluginName, profile, callbackInterface,
                         QStringLiteral("twitter"),
                         SocialNetworkSyncAdaptor::dataTypeName(SocialNetworkSyncAdaptor::Notifications))
{
    QString translationPath("/usr/share/translations/");
    // QTranslator life-cycle: owned by ButeoSocial and removed by its own destructor
    QTranslator *engineeringEnglish = new QTranslator(this);
    engineeringEnglish->load("lipstick-jolla-home-twitter-notif_eng_en", translationPath);
    QCoreApplication::instance()->installTranslator(engineeringEnglish);

    QTranslator *translator = new QTranslator(this);
    translator->load(QLocale(), "lipstick-jolla-home-twitter-notif", "-", translationPath);
    QCoreApplication::instance()->installTranslator(translator);
}

TwitterNotificationsPlugin::~TwitterNotificationsPlugin()
{
}

SocialNetworkSyncAdaptor *TwitterNotificationsPlugin::createSocialNetworkSyncAdaptor()
{
    return new TwitterMentionTimelineSyncAdaptor(this);
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreD3D11HardwareBuffer.h"
#include "OgreD3D11Device.h"

namespace Ogre {

	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
		size_t numVertices, HardwareBuffer::Usage usage, D3D11Device & device,
		bool useSystemMemory, bool useShadowBuffer)
		: HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, useSystemMemory, useShadowBuffer)
	{
		// everything is done via internal generalisation
		mBufferImpl = new D3D11HardwareBuffer(D3D11HardwareBuffer::VERTEX_BUFFER,
			mSizeInBytes, mUsage, device, useSystemMemory, useShadowBuffer);

	}
	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::~D3D11HardwareVertexBuffer()
	{
		delete mBufferImpl;
	}
	//---------------------------------------------------------------------
	void* D3D11HardwareVertexBuffer::lock(size_t offset, size_t length, LockOptions options)
	{
		return mBufferImpl->lock(offset, length, options);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::unlock(void)
	{
		mBufferImpl->unlock();
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::readData(size_t offset, size_t length, void* pDest)
	{
		mBufferImpl->readData(offset, length, pDest);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::writeData(size_t offset, size_t length, const void* pSource,
		bool discardWholeBuffer)
	{
		mBufferImpl->writeData(offset, length, pSource, discardWholeBuffer);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
		size_t dstOffset, size_t length, bool discardWholeBuffer)
	{
		D3D11HardwareVertexBuffer& d3dBuf = static_cast<D3D11HardwareVertexBuffer&>(srcBuffer);

		mBufferImpl->copyData(*(d3dBuf.mBufferImpl), srcOffset, dstOffset, length, discardWholeBuffer);
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::isLocked(void) const
	{
		return mBufferImpl->isLocked();
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::releaseIfDefaultPool(void)
	{
		/*		if (mD3DPool == D3DPOOL_DEFAULT)
		{
		SAFE_RELEASE(mlpD3DBuffer);
		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::recreateIfDefaultPool(D3D11Device & device)
	{
		/*	if (mD3DPool == D3DPOOL_DEFAULT)
		{
		// Create the Index buffer
		HRESULT hr = device->CreateIndexBuffer(
		static_cast<UINT>(mSizeInBytes),
		D3D11Mappings::get(mUsage),
		D3D11Mappings::get(mIndexType),
		mD3DPool,
		&mlpD3DBuffer,
		NULL
		);

		if (FAILED(hr))
		{
		String msg = DXGetErrorDescription(hr);
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
		"Cannot create D3D11 Index buffer: " + msg,
		"D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer");
		}

		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	ID3D11Buffer * D3D11HardwareVertexBuffer::getD3DVertexBuffer( void ) const
	{
		return mBufferImpl->getD3DBuffer();
	}
	//---------------------------------------------------------------------

}

<commit_msg>D3D11 render system: Added code to support copy of vertex buffers that where allocated in system memory. (The terrain sample does such a copy).<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreD3D11HardwareBuffer.h"
#include "OgreD3D11Device.h"

namespace Ogre {

	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
		size_t numVertices, HardwareBuffer::Usage usage, D3D11Device & device,
		bool useSystemMemory, bool useShadowBuffer)
		: HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, useSystemMemory, useShadowBuffer),
		  mBufferImpl(0)

	{
		// everything is done via internal generalisation
		mBufferImpl = new D3D11HardwareBuffer(D3D11HardwareBuffer::VERTEX_BUFFER,
			mSizeInBytes, mUsage, device, useSystemMemory, useShadowBuffer);

	}
	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::~D3D11HardwareVertexBuffer()
	{
		SAFE_DELETE(mBufferImpl);
	}
	//---------------------------------------------------------------------
	void* D3D11HardwareVertexBuffer::lock(size_t offset, size_t length, LockOptions options)
	{
		return mBufferImpl->lock(offset, length, options);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::unlock(void)
	{
		mBufferImpl->unlock();
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::readData(size_t offset, size_t length, void* pDest)
	{
		mBufferImpl->readData(offset, length, pDest);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::writeData(size_t offset, size_t length, const void* pSource,
		bool discardWholeBuffer)
	{
		mBufferImpl->writeData(offset, length, pSource, discardWholeBuffer);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
		size_t dstOffset, size_t length, bool discardWholeBuffer)
	{
		// check if the other buffer is also a D3D11HardwareVertexBuffer
		if (srcBuffer.isSystemMemory())
		{
			// src is not not a D3D11HardwareVertexBuffer - use default copy
			HardwareBuffer::copyData(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
		}
		else
		{
			// src is a D3D11HardwareVertexBuffer use d3d11 optimized copy
			D3D11HardwareVertexBuffer& d3dBuf = static_cast<D3D11HardwareVertexBuffer&>(srcBuffer);

			mBufferImpl->copyData(*(d3dBuf.mBufferImpl), srcOffset, dstOffset, length, discardWholeBuffer);
		}
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::isLocked(void) const
	{
		return mBufferImpl->isLocked();
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::releaseIfDefaultPool(void)
	{
		/*		if (mD3DPool == D3DPOOL_DEFAULT)
		{
		SAFE_RELEASE(mlpD3DBuffer);
		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::recreateIfDefaultPool(D3D11Device & device)
	{
		/*	if (mD3DPool == D3DPOOL_DEFAULT)
		{
		// Create the Index buffer
		HRESULT hr = device->CreateIndexBuffer(
		static_cast<UINT>(mSizeInBytes),
		D3D11Mappings::get(mUsage),
		D3D11Mappings::get(mIndexType),
		mD3DPool,
		&mlpD3DBuffer,
		NULL
		);

		if (FAILED(hr))
		{
		String msg = DXGetErrorDescription(hr);
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
		"Cannot create D3D11 Index buffer: " + msg,
		"D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer");
		}

		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	ID3D11Buffer * D3D11HardwareVertexBuffer::getD3DVertexBuffer( void ) const
	{
		return mBufferImpl->getD3DBuffer();
	}
	//---------------------------------------------------------------------

}

<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#include "mbed-drivers/mbed.h"
#include "ble/BLE.h"

BLE ble;
DigitalOut  led1(LED1, 1);
InterruptIn button(BUTTON1);
uint8_t count;

const char DEVICE_NAME[] = "Button";

void buttonPressedCallback(void)
{
    count++;
    ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, &count, sizeof(count));
}

void blinkCallback(void)
{
    led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */
}

void app_start(int, char**)
{
    ble.init();

    /* setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms. */

    count = 0;
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, &count, sizeof(count));
    minar::Scheduler::postCallback(blinkCallback).period(minar::milliseconds(500));
    button.rise(buttonPressedCallback);

    ble.gap().startAdvertising();
}
<commit_msg>Change device name to GapButton to uniquely identify this demo.<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#include "mbed-drivers/mbed.h"
#include "ble/BLE.h"

BLE ble;
DigitalOut  led1(LED1, 1);
InterruptIn button(BUTTON1);
uint8_t count;

const char DEVICE_NAME[] = "GapButton";

void buttonPressedCallback(void)
{
    count++;
    ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, &count, sizeof(count));
}

void blinkCallback(void)
{
    led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */
}

void app_start(int, char**)
{
    ble.init();

    /* setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms. */

    count = 0;
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, &count, sizeof(count));
    minar::Scheduler::postCallback(blinkCallback).period(minar::milliseconds(500));
    button.rise(buttonPressedCallback);

    ble.gap().startAdvertising();
}
<|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.
 *
 *=========================================================================*/
#ifndef __itkGaussianDerivativeImageFunction_hxx
#define __itkGaussianDerivativeImageFunction_hxx

#include "itkGaussianDerivativeImageFunction.h"

#include "itkCompensatedSummation.h"

namespace itk
{
/** Set the Input Image */
template< typename TInputImage, typename TOutput >
GaussianDerivativeImageFunction< TInputImage, TOutput >
::GaussianDerivativeImageFunction()
{
  typename GaussianFunctionType::ArrayType mean;
  mean[0] = 0.0;
  for ( unsigned int i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    m_Sigma[i] = 1.0;
    m_Extent[i] = 1.0;
    }
  m_UseImageSpacing = true;
  m_GaussianDerivativeFunction = GaussianDerivativeFunctionType::New();
  m_GaussianFunction = GaussianFunctionType::New();
  m_OperatorImageFunction = OperatorImageFunctionType::New();
  m_GaussianFunction->SetMean(mean);
  m_GaussianFunction->SetNormalized(false);           // faster
  m_GaussianDerivativeFunction->SetNormalized(false); // faster
  this->RecomputeGaussianKernel();
}

/** Print self method */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::PrintSelf(std::ostream & os, Indent indent) const
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "UseImageSpacing: " << m_UseImageSpacing << std::endl;

  os << indent << "Sigma: " << m_Sigma << std::endl;
  os << indent << "Extent: " << m_Extent << std::endl;

  os << indent << "OperatorArray: " << m_OperatorArray << std::endl;
  os << indent << "ContinuousOperatorArray: "
     << m_ContinuousOperatorArray << std::endl;
  os << indent << "OperatorImageFunction: "
     << m_OperatorImageFunction << std::endl;
  os << indent << "GaussianDerivativeFunction: "
     << m_GaussianDerivativeFunction << std::endl;
  os << indent << "GaussianFunction: "
     << m_GaussianFunction << std::endl;
}

/** Set the input image */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetInputImage(const InputImageType *ptr)
{
  Superclass::SetInputImage(ptr);
  m_OperatorImageFunction->SetInputImage(ptr);
}

/** Set the variance of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetSigma(const double *sigma)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( sigma[i] != m_Sigma[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Sigma[i] = sigma[i];
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the variance of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetSigma(const double sigma)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( sigma != m_Sigma[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Sigma[i] = sigma;
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the extent of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetExtent(const double *extent)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( extent[i] != m_Extent[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Extent[i] = extent[i];
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the extent of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetExtent(const double extent)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( extent != m_Extent[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Extent[i] = extent;
      }
    this->RecomputeGaussianKernel();
    }
}

/** Recompute the gaussian kernel used to evaluate indexes
 *  This should use a fastest Derivative Gaussian operator
 */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::RecomputeGaussianKernel()
{
  unsigned int direction = 0;

  for ( unsigned int op = 0; op < itkGetStaticConstMacro(ImageDimension2); ++op )
    {
    // Set the derivative of the gaussian first
    OperatorNeighborhoodType dogNeighborhood;
    typename GaussianDerivativeFunctionType::InputType pt;
    typename NeighborhoodType::SizeType size;
    size.Fill(0);
    size[direction] = static_cast<SizeValueType>( m_Sigma[direction] * m_Extent[direction] );
    dogNeighborhood.SetRadius(size);

    typename GaussianDerivativeFunctionType::ArrayType s;
    s[0] = m_Sigma[direction];
    m_GaussianDerivativeFunction->SetSigma(s);

    typename OperatorNeighborhoodType::Iterator it = dogNeighborhood.Begin();

    unsigned int i = 0;
    while ( it != dogNeighborhood.End() )
      {
      pt[0] = dogNeighborhood.GetOffset(i)[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }
      ( *it ) = m_GaussianDerivativeFunction->Evaluate(pt);
      ++i;
      ++it;
      }

    m_OperatorArray[op * 2] = dogNeighborhood;

    // Set the gaussian operator
    m_GaussianFunction->SetSigma(s);
    OperatorNeighborhoodType gaussianNeighborhood;
    gaussianNeighborhood.SetRadius(size);

    it = gaussianNeighborhood.Begin();

    i = 0;
    double sum = 0.0;
    while ( it != gaussianNeighborhood.End() )
      {
      pt[0] = gaussianNeighborhood.GetOffset(i)[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }

      ( *it ) = m_GaussianFunction->Evaluate(pt);
      sum += ( *it );
      ++i;
      ++it;
      }

    // Make the filter DC-Constant
    it = gaussianNeighborhood.Begin();
    while ( it != gaussianNeighborhood.End() )
      {
      ( *it ) /= sum;
      ++it;
      }

    m_OperatorArray[op * 2 + 1] = gaussianNeighborhood;
    ++direction;
    }
}

/** Evaluate the function at the specifed index */
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::EvaluateAtIndex(const IndexType & index) const
{
  OutputType gradient;

  for ( unsigned int ii = 0; ii < itkGetStaticConstMacro(ImageDimension2); ++ii )
    {
    // Apply each gaussian kernel to a subset of the image
    InputPixelType value = static_cast< double >( this->GetInputImage()->GetPixel(index) );

    // gaussian blurring first
    for ( unsigned int direction = 0; direction < itkGetStaticConstMacro(ImageDimension2); ++direction )
      {
      if ( ii != direction )
        {
        const unsigned int idx = 2 * direction + 1; // select only gaussian kernel;
        const unsigned int center = (unsigned int)( ( m_OperatorArray[idx].GetSize()[direction] - 1 ) / 2 );
        TOutput      centerval = m_OperatorArray[idx].GetCenterValue();
        m_OperatorArray[idx][center] = 0;
        m_OperatorImageFunction->SetOperator(m_OperatorArray[idx]);
        value = m_OperatorImageFunction->EvaluateAtIndex(index) + centerval * value;
        }
      }

    // then derivative in the direction
    const unsigned int idx = 2 * ii;
    const signed int center = (unsigned int)( ( m_OperatorArray[idx].GetSize()[ii] - 1 ) / 2 );
    TOutput    centerval = m_OperatorArray[idx].GetCenterValue();
    m_OperatorArray[idx][center] = 0;
    m_OperatorImageFunction->SetOperator(m_OperatorArray[idx]);
    value = m_OperatorImageFunction->EvaluateAtIndex(index) + centerval * value;

    gradient[ii] = value;
    }

  return gradient;
}

/** Recompute the gaussian kernel used to evaluate indexes
 *  The variance should be uniform */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::RecomputeContinuousGaussianKernel(
  const double *offset) const
{
  unsigned int direction = 0;

  for ( unsigned int op = 0; op < itkGetStaticConstMacro(ImageDimension2); ++op )
    {
    // Set the derivative of the gaussian first
    OperatorNeighborhoodType dogNeighborhood;
    typename GaussianDerivativeFunctionType::InputType pt;
    typename OperatorNeighborhoodType::SizeType size;
    size.Fill(0);
    size[direction] = static_cast<SizeValueType>( m_Sigma[direction] * m_Extent[direction] );
    dogNeighborhood.SetRadius(size);

    typename GaussianDerivativeFunctionType::ArrayType s;
    s[0] = m_Sigma[direction];
    m_GaussianDerivativeFunction->SetSigma(s);

    typename OperatorNeighborhoodType::Iterator it = dogNeighborhood.Begin();

    unsigned int ii = 0;
    while ( it != dogNeighborhood.End() )
      {
      pt[0] = dogNeighborhood.GetOffset(ii)[direction] - offset[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }
      ( *it ) = m_GaussianDerivativeFunction->Evaluate(pt);
      ++ii;
      ++it;
      }

    m_ContinuousOperatorArray[op * 2] = dogNeighborhood;

    // Set the gaussian operator
    m_GaussianFunction->SetSigma(s);
    OperatorNeighborhoodType gaussianNeighborhood;
    gaussianNeighborhood.SetRadius(size);

    it = gaussianNeighborhood.Begin();

    ii = 0;
    double sum = 0;
    while ( it != gaussianNeighborhood.End() )
      {
      pt[0] = gaussianNeighborhood.GetOffset(ii)[direction] - offset[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }

      ( *it ) = m_GaussianFunction->Evaluate(pt);
      sum += ( *it );
      ++ii;
      ++it;
      }

    // Make the filter DC-Constant
    it = gaussianNeighborhood.Begin();
    while ( it != gaussianNeighborhood.End() )
      {
      ( *it ) /= sum;
      ++it;
      }

    m_ContinuousOperatorArray[op * 2 + 1] = gaussianNeighborhood;
    ++direction;
    }
}

/** Evaluate the function at the specifed point */
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::Evaluate(const PointType & point) const
{
  IndexType index;

  this->ConvertPointToNearestIndex(point, index);
  return this->EvaluateAtIndex (index);
}

/** Evaluate the function at specified ContinousIndex position.*/
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const
{
  IndexType index;

  this->ConvertContinuousIndexToNearestIndex(cindex, index);
  return this->EvaluateAtIndex(index);
}
} // end namespace itk

#endif
<commit_msg>ENH: Use CompensatedSummation in GaussianDerivativeImageFunction.<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.
 *
 *=========================================================================*/
#ifndef __itkGaussianDerivativeImageFunction_hxx
#define __itkGaussianDerivativeImageFunction_hxx

#include "itkGaussianDerivativeImageFunction.h"

#include "itkCompensatedSummation.h"

namespace itk
{
/** Set the Input Image */
template< typename TInputImage, typename TOutput >
GaussianDerivativeImageFunction< TInputImage, TOutput >
::GaussianDerivativeImageFunction()
{
  typename GaussianFunctionType::ArrayType mean;
  mean[0] = 0.0;
  for ( unsigned int i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    m_Sigma[i] = 1.0;
    m_Extent[i] = 1.0;
    }
  m_UseImageSpacing = true;
  m_GaussianDerivativeFunction = GaussianDerivativeFunctionType::New();
  m_GaussianFunction = GaussianFunctionType::New();
  m_OperatorImageFunction = OperatorImageFunctionType::New();
  m_GaussianFunction->SetMean(mean);
  m_GaussianFunction->SetNormalized(false);           // faster
  m_GaussianDerivativeFunction->SetNormalized(false); // faster
  this->RecomputeGaussianKernel();
}

/** Print self method */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::PrintSelf(std::ostream & os, Indent indent) const
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "UseImageSpacing: " << m_UseImageSpacing << std::endl;

  os << indent << "Sigma: " << m_Sigma << std::endl;
  os << indent << "Extent: " << m_Extent << std::endl;

  os << indent << "OperatorArray: " << m_OperatorArray << std::endl;
  os << indent << "ContinuousOperatorArray: "
     << m_ContinuousOperatorArray << std::endl;
  os << indent << "OperatorImageFunction: "
     << m_OperatorImageFunction << std::endl;
  os << indent << "GaussianDerivativeFunction: "
     << m_GaussianDerivativeFunction << std::endl;
  os << indent << "GaussianFunction: "
     << m_GaussianFunction << std::endl;
}

/** Set the input image */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetInputImage(const InputImageType *ptr)
{
  Superclass::SetInputImage(ptr);
  m_OperatorImageFunction->SetInputImage(ptr);
}

/** Set the variance of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetSigma(const double *sigma)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( sigma[i] != m_Sigma[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Sigma[i] = sigma[i];
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the variance of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetSigma(const double sigma)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( sigma != m_Sigma[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Sigma[i] = sigma;
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the extent of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetExtent(const double *extent)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( extent[i] != m_Extent[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Extent[i] = extent[i];
      }
    this->RecomputeGaussianKernel();
    }
}

/** Set the extent of the gaussian in each direction */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::SetExtent(const double extent)
{
  unsigned int i;

  for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
    {
    if ( extent != m_Extent[i] )
      {
      break;
      }
    }
  if ( i < itkGetStaticConstMacro(ImageDimension2) )
    {
    for ( i = 0; i < itkGetStaticConstMacro(ImageDimension2); i++ )
      {
      m_Extent[i] = extent;
      }
    this->RecomputeGaussianKernel();
    }
}

/** Recompute the gaussian kernel used to evaluate indexes
 *  This should use a fastest Derivative Gaussian operator
 */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::RecomputeGaussianKernel()
{
  unsigned int direction = 0;

  for ( unsigned int op = 0; op < itkGetStaticConstMacro(ImageDimension2); ++op )
    {
    // Set the derivative of the gaussian first
    OperatorNeighborhoodType dogNeighborhood;
    typename GaussianDerivativeFunctionType::InputType pt;
    typename NeighborhoodType::SizeType size;
    size.Fill(0);
    size[direction] = static_cast<SizeValueType>( m_Sigma[direction] * m_Extent[direction] );
    dogNeighborhood.SetRadius(size);

    typename GaussianDerivativeFunctionType::ArrayType s;
    s[0] = m_Sigma[direction];
    m_GaussianDerivativeFunction->SetSigma(s);

    typename OperatorNeighborhoodType::Iterator it = dogNeighborhood.Begin();

    unsigned int i = 0;
    while ( it != dogNeighborhood.End() )
      {
      pt[0] = dogNeighborhood.GetOffset(i)[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }
      ( *it ) = m_GaussianDerivativeFunction->Evaluate(pt);
      ++i;
      ++it;
      }

    m_OperatorArray[op * 2] = dogNeighborhood;

    // Set the gaussian operator
    m_GaussianFunction->SetSigma(s);
    OperatorNeighborhoodType gaussianNeighborhood;
    gaussianNeighborhood.SetRadius(size);

    it = gaussianNeighborhood.Begin();

    i = 0;
    CompensatedSummation< TOutput > sum;
    while ( it != gaussianNeighborhood.End() )
      {
      pt[0] = gaussianNeighborhood.GetOffset(i)[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }

      ( *it ) = m_GaussianFunction->Evaluate(pt);
      sum += ( *it );
      ++i;
      ++it;
      }

    // Make the filter DC-Constant
    it = gaussianNeighborhood.Begin();
    const TOutput sumInverse = 1. / sum.GetSum();
    while ( it != gaussianNeighborhood.End() )
      {
      ( *it ) *= sumInverse;
      ++it;
      }

    m_OperatorArray[op * 2 + 1] = gaussianNeighborhood;
    ++direction;
    }
}

/** Evaluate the function at the specifed index */
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::EvaluateAtIndex(const IndexType & index) const
{
  OutputType gradient;

  for ( unsigned int ii = 0; ii < itkGetStaticConstMacro(ImageDimension2); ++ii )
    {
    // Apply each gaussian kernel to a subset of the image
    InputPixelType value = static_cast< double >( this->GetInputImage()->GetPixel(index) );

    // gaussian blurring first
    for ( unsigned int direction = 0; direction < itkGetStaticConstMacro(ImageDimension2); ++direction )
      {
      if ( ii != direction )
        {
        const unsigned int idx = 2 * direction + 1; // select only gaussian kernel;
        const unsigned int center = (unsigned int)( ( m_OperatorArray[idx].GetSize()[direction] - 1 ) / 2 );
        TOutput      centerval = m_OperatorArray[idx].GetCenterValue();
        m_OperatorArray[idx][center] = 0;
        m_OperatorImageFunction->SetOperator(m_OperatorArray[idx]);
        value = m_OperatorImageFunction->EvaluateAtIndex(index) + centerval * value;
        }
      }

    // then derivative in the direction
    const unsigned int idx = 2 * ii;
    const signed int center = (unsigned int)( ( m_OperatorArray[idx].GetSize()[ii] - 1 ) / 2 );
    TOutput    centerval = m_OperatorArray[idx].GetCenterValue();
    m_OperatorArray[idx][center] = 0;
    m_OperatorImageFunction->SetOperator(m_OperatorArray[idx]);
    value = m_OperatorImageFunction->EvaluateAtIndex(index) + centerval * value;

    gradient[ii] = value;
    }

  return gradient;
}

/** Recompute the gaussian kernel used to evaluate indexes
 *  The variance should be uniform */
template< typename TInputImage, typename TOutput >
void
GaussianDerivativeImageFunction< TInputImage, TOutput >
::RecomputeContinuousGaussianKernel(
  const double *offset) const
{
  unsigned int direction = 0;

  for ( unsigned int op = 0; op < itkGetStaticConstMacro(ImageDimension2); ++op )
    {
    // Set the derivative of the gaussian first
    OperatorNeighborhoodType dogNeighborhood;
    typename GaussianDerivativeFunctionType::InputType pt;
    typename OperatorNeighborhoodType::SizeType size;
    size.Fill(0);
    size[direction] = static_cast<SizeValueType>( m_Sigma[direction] * m_Extent[direction] );
    dogNeighborhood.SetRadius(size);

    typename GaussianDerivativeFunctionType::ArrayType s;
    s[0] = m_Sigma[direction];
    m_GaussianDerivativeFunction->SetSigma(s);

    typename OperatorNeighborhoodType::Iterator it = dogNeighborhood.Begin();

    unsigned int ii = 0;
    while ( it != dogNeighborhood.End() )
      {
      pt[0] = dogNeighborhood.GetOffset(ii)[direction] - offset[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }
      ( *it ) = m_GaussianDerivativeFunction->Evaluate(pt);
      ++ii;
      ++it;
      }

    m_ContinuousOperatorArray[op * 2] = dogNeighborhood;

    // Set the gaussian operator
    m_GaussianFunction->SetSigma(s);
    OperatorNeighborhoodType gaussianNeighborhood;
    gaussianNeighborhood.SetRadius(size);

    it = gaussianNeighborhood.Begin();

    ii = 0;
    CompensatedSummation< TOutput > sum;
    while ( it != gaussianNeighborhood.End() )
      {
      pt[0] = gaussianNeighborhood.GetOffset(ii)[direction] - offset[direction];

      if ( ( m_UseImageSpacing == true ) && ( this->GetInputImage() ) )
        {
        if ( this->GetInputImage()->GetSpacing()[direction] == 0.0 )
          {
          itkExceptionMacro(<< "Pixel spacing cannot be zero");
          }
        else
          {
          pt[0] *= this->GetInputImage()->GetSpacing()[direction];
          }
        }

      ( *it ) = m_GaussianFunction->Evaluate(pt);
      sum += ( *it );
      ++ii;
      ++it;
      }

    // Make the filter DC-Constant
    it = gaussianNeighborhood.Begin();
    const TOutput sumInverse = 1. / sum.GetSum();
    while ( it != gaussianNeighborhood.End() )
      {
      ( *it ) *= sumInverse;
      ++it;
      }

    m_ContinuousOperatorArray[op * 2 + 1] = gaussianNeighborhood;
    ++direction;
    }
}

/** Evaluate the function at the specifed point */
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::Evaluate(const PointType & point) const
{
  IndexType index;

  this->ConvertPointToNearestIndex(point, index);
  return this->EvaluateAtIndex (index);
}

/** Evaluate the function at specified ContinousIndex position.*/
template< typename TInputImage, typename TOutput >
typename GaussianDerivativeImageFunction< TInputImage, TOutput >::OutputType
GaussianDerivativeImageFunction< TInputImage, TOutput >
::EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const
{
  IndexType index;

  this->ConvertContinuousIndexToNearestIndex(cindex, index);
  return this->EvaluateAtIndex(index);
}
} // end namespace itk

#endif
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include <mitkManualSegmentationToSurfaceFilter.h>

#include <vtkImageShiftScale.h>
#include <vtkSmartPointer.h>

#include "mitkProgressBar.h"

mitk::ManualSegmentationToSurfaceFilter::ManualSegmentationToSurfaceFilter()
{
  m_MedianFilter3D = false;
  m_MedianKernelSizeX = 3;
  m_MedianKernelSizeY = 3;
  m_MedianKernelSizeZ = 3;
  m_UseGaussianImageSmooth = false;
  m_GaussianStandardDeviation = 1.5;
  m_Interpolation = false;
  m_InterpolationX = 1.0f;
  m_InterpolationY = 1.0f;
  m_InterpolationZ = 1.0f;
};

mitk::ManualSegmentationToSurfaceFilter::~ManualSegmentationToSurfaceFilter(){};

void mitk::ManualSegmentationToSurfaceFilter::GenerateData()
{
  mitk::Surface *surface = this->GetOutput();
  auto *image = (mitk::Image *)GetInput();
  mitk::Image::RegionType outputRegion = image->GetRequestedRegion();

  int tstart = outputRegion.GetIndex(3);
  int tmax = tstart + outputRegion.GetSize(3); // GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloest

  ScalarType thresholdExpanded = this->m_Threshold;

  if ((tmax - tstart) > 0)
  {
    ProgressBar::GetInstance()->AddStepsToDo(4 * (tmax - tstart));
  }
  else
  {
    ProgressBar::GetInstance()->AddStepsToDo(4);
  }

  for (int t = tstart; t < tmax; ++t)
  {
    vtkSmartPointer<vtkImageData> vtkimage = image->GetVtkImageData(t);

    // Median -->smooth 3D
    // MITK_INFO << (m_MedianFilter3D ? "Applying median..." : "No median filtering");
    if (m_MedianFilter3D)
    {
      vtkImageMedian3D *median = vtkImageMedian3D::New();
      median->SetInputData(vtkimage);                                                       // RC++ (VTK < 5.0)
      median->SetKernelSize(m_MedianKernelSizeX, m_MedianKernelSizeY, m_MedianKernelSizeZ); // Std: 3x3x3
      median->ReleaseDataFlagOn();
      median->UpdateInformation();
      median->Update();
      vtkimage = median->GetOutput(); //->Out
      median->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // Interpolate image spacing
    // MITK_INFO << (m_Interpolation ? "Resampling..." : "No resampling");
    if (m_Interpolation)
    {
      vtkImageResample *imageresample = vtkImageResample::New();
      imageresample->SetInputData(vtkimage);

      // Set Spacing Manual to 1mm in each direction (Original spacing is lost during image processing)
      imageresample->SetAxisOutputSpacing(0, m_InterpolationX);
      imageresample->SetAxisOutputSpacing(1, m_InterpolationY);
      imageresample->SetAxisOutputSpacing(2, m_InterpolationZ);
      imageresample->UpdateInformation();
      imageresample->Update();
      vtkimage = imageresample->GetOutput(); //->Output
      imageresample->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // MITK_INFO << (m_UseGaussianImageSmooth ? "Applying gaussian smoothing..." : "No gaussian smoothing");
    if (m_UseGaussianImageSmooth) // gauss
    {
      vtkImageShiftScale *scalefilter = vtkImageShiftScale::New();
      scalefilter->SetScale(100);
      scalefilter->SetInputData(vtkimage);
      scalefilter->Update();

      vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
      gaussian->SetInputConnection(scalefilter->GetOutputPort());
      gaussian->SetDimensionality(3);
      gaussian->SetRadiusFactor(0.49);
      gaussian->SetStandardDeviation(m_GaussianStandardDeviation);
      gaussian->ReleaseDataFlagOn();
      gaussian->UpdateInformation();
      gaussian->Update();

      vtkimage = scalefilter->GetOutput();

      double range[2];
      vtkimage->GetScalarRange(range);

      if (range[1] != 0) // too little slices, image smoothing eliminates all segmentation pixels
      {
        vtkimage = gaussian->GetOutput(); //->Out
      }
      else
      {
        MITK_INFO << "Smoothing would remove all pixels of the segmentation. Use unsmoothed result instead.";
      }
      gaussian->Delete();
      scalefilter->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // Create surface for t-Slice
    CreateSurface(t, vtkimage, surface, thresholdExpanded);
    ProgressBar::GetInstance()->Progress();
  }

  // MITK_INFO << "Updating Time Geometry to ensure right timely displaying";
  // Fixing wrong time geometry
  TimeGeometry *surfaceTG = surface->GetTimeGeometry();
  auto *surfacePTG = dynamic_cast<ProportionalTimeGeometry *>(surfaceTG);
  TimeGeometry *imageTG = image->GetTimeGeometry();
  auto *imagePTG = dynamic_cast<ProportionalTimeGeometry *>(imageTG);
  // Requires ProportionalTimeGeometries to work. May not be available for all steps.
  assert(surfacePTG != nullptr);
  assert(imagePTG != nullptr);
  if ((surfacePTG != nullptr) && (imagePTG != nullptr))
  {
    TimePointType firstTime = imagePTG->GetFirstTimePoint();
    TimePointType duration = imagePTG->GetStepDuration();
    surfacePTG->SetFirstTimePoint(firstTime);
    surfacePTG->SetStepDuration(duration);
    // MITK_INFO << "First Time Point: " << firstTime << "  Duration: " << duration;
  }
};

void mitk::ManualSegmentationToSurfaceFilter::SetMedianKernelSize(int x, int y, int z)
{
  m_MedianKernelSizeX = x;
  m_MedianKernelSizeY = y;
  m_MedianKernelSizeZ = z;
}

void mitk::ManualSegmentationToSurfaceFilter::SetInterpolation(vtkDouble x, vtkDouble y, vtkDouble z)
{
  m_InterpolationX = x;
  m_InterpolationY = y;
  m_InterpolationZ = z;
}
<commit_msg>Pad single-sliced images with empty slice to make them 3-d for VTK<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#include <array>

#include <mitkManualSegmentationToSurfaceFilter.h>

#include <vtkImageShiftScale.h>
#include <vtkImageConstantPad.h>
#include <vtkSmartPointer.h>

#include "mitkProgressBar.h"

mitk::ManualSegmentationToSurfaceFilter::ManualSegmentationToSurfaceFilter()
{
  m_MedianFilter3D = false;
  m_MedianKernelSizeX = 3;
  m_MedianKernelSizeY = 3;
  m_MedianKernelSizeZ = 3;
  m_UseGaussianImageSmooth = false;
  m_GaussianStandardDeviation = 1.5;
  m_Interpolation = false;
  m_InterpolationX = 1.0f;
  m_InterpolationY = 1.0f;
  m_InterpolationZ = 1.0f;
};

mitk::ManualSegmentationToSurfaceFilter::~ManualSegmentationToSurfaceFilter(){};

void mitk::ManualSegmentationToSurfaceFilter::GenerateData()
{
  mitk::Surface *surface = this->GetOutput();
  auto *image = (mitk::Image *)GetInput();
  mitk::Image::RegionType outputRegion = image->GetRequestedRegion();

  int tstart = outputRegion.GetIndex(3);
  int tmax = tstart + outputRegion.GetSize(3); // GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloest

  ScalarType thresholdExpanded = this->m_Threshold;

  if ((tmax - tstart) > 0)
  {
    ProgressBar::GetInstance()->AddStepsToDo(4 * (tmax - tstart));
  }
  else
  {
    ProgressBar::GetInstance()->AddStepsToDo(4);
  }

  for (int t = tstart; t < tmax; ++t)
  {
    vtkSmartPointer<vtkImageData> vtkimage = image->GetVtkImageData(t);

    // If the image has a single slice, pad it with an empty slice to explicitly make it
    // recognizable as 3-d by VTK. Otherwise, the vtkMarchingCubes filter will
    // complain about dimensionality and won't produce any output.
    if (2 == vtkimage->GetDataDimension())
    {
      std::array<int, 6> extent;
      vtkimage->GetExtent(extent.data());
      extent[5] = 1;

      auto padFilter = vtkSmartPointer<vtkImageConstantPad>::New();
      padFilter->SetInputData(vtkimage);
      padFilter->SetOutputWholeExtent(extent.data());
      padFilter->UpdateInformation();
      padFilter->Update();
      vtkimage = padFilter->GetOutput();
    }

    // Median -->smooth 3D
    // MITK_INFO << (m_MedianFilter3D ? "Applying median..." : "No median filtering");
    if (m_MedianFilter3D)
    {
      vtkImageMedian3D *median = vtkImageMedian3D::New();
      median->SetInputData(vtkimage);                                                       // RC++ (VTK < 5.0)
      median->SetKernelSize(m_MedianKernelSizeX, m_MedianKernelSizeY, m_MedianKernelSizeZ); // Std: 3x3x3
      median->ReleaseDataFlagOn();
      median->UpdateInformation();
      median->Update();
      vtkimage = median->GetOutput(); //->Out
      median->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // Interpolate image spacing
    // MITK_INFO << (m_Interpolation ? "Resampling..." : "No resampling");
    if (m_Interpolation)
    {
      vtkImageResample *imageresample = vtkImageResample::New();
      imageresample->SetInputData(vtkimage);

      // Set Spacing Manual to 1mm in each direction (Original spacing is lost during image processing)
      imageresample->SetAxisOutputSpacing(0, m_InterpolationX);
      imageresample->SetAxisOutputSpacing(1, m_InterpolationY);
      imageresample->SetAxisOutputSpacing(2, m_InterpolationZ);
      imageresample->UpdateInformation();
      imageresample->Update();
      vtkimage = imageresample->GetOutput(); //->Output
      imageresample->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // MITK_INFO << (m_UseGaussianImageSmooth ? "Applying gaussian smoothing..." : "No gaussian smoothing");
    if (m_UseGaussianImageSmooth) // gauss
    {
      vtkImageShiftScale *scalefilter = vtkImageShiftScale::New();
      scalefilter->SetScale(100);
      scalefilter->SetInputData(vtkimage);
      scalefilter->Update();

      vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
      gaussian->SetInputConnection(scalefilter->GetOutputPort());
      gaussian->SetDimensionality(3);
      gaussian->SetRadiusFactor(0.49);
      gaussian->SetStandardDeviation(m_GaussianStandardDeviation);
      gaussian->ReleaseDataFlagOn();
      gaussian->UpdateInformation();
      gaussian->Update();

      vtkimage = scalefilter->GetOutput();

      double range[2];
      vtkimage->GetScalarRange(range);

      if (range[1] != 0) // too little slices, image smoothing eliminates all segmentation pixels
      {
        vtkimage = gaussian->GetOutput(); //->Out
      }
      else
      {
        MITK_INFO << "Smoothing would remove all pixels of the segmentation. Use unsmoothed result instead.";
      }
      gaussian->Delete();
      scalefilter->Delete();
    }
    ProgressBar::GetInstance()->Progress();

    // Create surface for t-Slice
    CreateSurface(t, vtkimage, surface, thresholdExpanded);
    ProgressBar::GetInstance()->Progress();
  }

  // MITK_INFO << "Updating Time Geometry to ensure right timely displaying";
  // Fixing wrong time geometry
  TimeGeometry *surfaceTG = surface->GetTimeGeometry();
  auto *surfacePTG = dynamic_cast<ProportionalTimeGeometry *>(surfaceTG);
  TimeGeometry *imageTG = image->GetTimeGeometry();
  auto *imagePTG = dynamic_cast<ProportionalTimeGeometry *>(imageTG);
  // Requires ProportionalTimeGeometries to work. May not be available for all steps.
  assert(surfacePTG != nullptr);
  assert(imagePTG != nullptr);
  if ((surfacePTG != nullptr) && (imagePTG != nullptr))
  {
    TimePointType firstTime = imagePTG->GetFirstTimePoint();
    TimePointType duration = imagePTG->GetStepDuration();
    surfacePTG->SetFirstTimePoint(firstTime);
    surfacePTG->SetStepDuration(duration);
    // MITK_INFO << "First Time Point: " << firstTime << "  Duration: " << duration;
  }
};

void mitk::ManualSegmentationToSurfaceFilter::SetMedianKernelSize(int x, int y, int z)
{
  m_MedianKernelSizeX = x;
  m_MedianKernelSizeY = y;
  m_MedianKernelSizeZ = z;
}

void mitk::ManualSegmentationToSurfaceFilter::SetInterpolation(vtkDouble x, vtkDouble y, vtkDouble z)
{
  m_InterpolationX = x;
  m_InterpolationY = y;
  m_InterpolationZ = z;
}
<|endoftext|>


<commit_before>// UVa1587 - Box
// Time:  O(1)
// Space: O(1)

#include <iostream>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>

using namespace std;

struct HashPair {
    size_t operator()(const pair<int, int>& p) const {
        return hash<int>()(p.first) ^ hash<int>()(p.second);
    }
};

int main() {
    int w, h;
    while (cin >> w >> h) {
        unordered_set<int> edge;
        unordered_map<pair<int, int>, int, HashPair> area;
        if (w > h) {
            swap(w, h);
        }
        edge.insert(w), edge.insert(h);
        ++area[make_pair(w, h)];

        int count = 5;
        while (count--) {
            cin >> w >> h;
            if (w > h) {
                swap(w, h);
            }
            edge.insert(w), edge.insert(h);
            ++area[make_pair(w, h)];
        }

        bool is_ok = false;

        // Make sure all of (w, h) has pairs and at most 3 different lengths of w, h, l.
        if (all_of(area.cbegin(), area.cend(), [](const pair<pair<int, int>, int>& p){ return p.second % 2 == 0; }) &&
            edge.size() <= 3) {
            is_ok = true;

            // Make sure all pairs of l, w, h exist.
            for (auto it = edge.cbegin(); is_ok && it != edge.cend(); ++it) {
                auto jt = it;
                ++jt;
                for (; is_ok && jt != edge.cend(); ++jt) {
                    if (area.find(make_pair(*it, *jt)) == area.cend() &&
                        area.find(make_pair(*jt, *it)) == area.cend()) { // Some of (w, h) does not exist.
                        is_ok = false;
                    }
                }
            }
        }

        if (is_ok) {
            cout << "POSSIBLE" << endl;
        } else {
            cout << "IMPOSSIBLE" << endl;
        }
    }

    return 0;
}<commit_msg>Update UVa1587.cpp<commit_after>// UVa1587 - Box
// Time:  O(1)
// Space: O(1)

#include <iostream>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>

using namespace std;

struct HashPair {
    size_t operator()(const pair<int, int>& p) const {
        return hash<int>()(p.first) ^ hash<int>()(p.second);
    }
};

void CheckBox(unordered_set<int>& edge, unordered_map<pair<int, int>, int, HashPair>& area) {
        bool is_ok = false;

        // Make sure all of (w, h) has pairs and at most 3 different lengths of w, h, l.
        if (all_of(area.cbegin(), area.cend(), [](const pair<pair<int, int>, int>& p){ return p.second % 2 == 0; }) &&
            edge.size() <= 3) {
            is_ok = true;

            // Make sure all pairs of l, w, h exist.
            for (auto it = edge.cbegin(); is_ok && it != edge.cend(); ++it) {
                auto jt = it;
                ++jt;
                for (; is_ok && jt != edge.cend(); ++jt) {
                    if (area.find(make_pair(*it, *jt)) == area.cend() &&
                        area.find(make_pair(*jt, *it)) == area.cend()) { // Some of (w, h) does not exist.
                        is_ok = false;
                    }
                }
            }
        }

        if (is_ok) {
            cout << "POSSIBLE" << endl;
        } else {
            cout << "IMPOSSIBLE" << endl;
        }
}

int main() {
    int w, h;
    while (cin >> w >> h) {
        unordered_set<int> edge;
        unordered_map<pair<int, int>, int, HashPair> area;
        int count = 0;
        do {
            if (w > h) {
                swap(w, h);
            }
            edge.insert(w), edge.insert(h);
            ++area[make_pair(w, h)];

            if (++count == 6) {
                break;
            }
        } while(cin >> w >> h);

        CheckBox(edge, area);
    }

    return 0;
}
<|endoftext|>


<commit_before>// UVa1588 - Kickdown
// Time:  O(m * n)
// Space: O(1)

#include <iostream>
#include <string>

using namespace std;

bool IsValid(int k, const string& s1, const string& s2){
    for (int i = 0; k + i < s1.length() && i < s2.length(); ++i) {
        if ((s1[k + i] - '0') + (s2[i] - '0') > 3) {
            return false;
        }
    }
    return true;
}

size_t Cut(const string& s1, const string& s2){
    int k = 0;
    while (!IsValid(k, s1, s2)) {
        ++k;
    }
    return max(s1.length(), s2.length() + k);
}

int main(){
    string bottom, top;
    while (cin >> bottom >> top) {
        cout << min(Cut(bottom, top), Cut(top, bottom)) << endl;
    }
    return 0;
}<commit_msg>update<commit_after>// Copyright (c) 2015 kamyu. All rights reserved.

/*
 * UVa1588 - Kickdown
 * http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4463
 *
 * Time  : O(m * n)
 * Space : O(1)
 *
 */

#include <iostream>
#include <string>
#include <algorithm>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::max;
using std::min;

bool IsValid(const int k, const string& s1, const string& s2) {
    for (int i = 0; k + i < s1.length() && i < s2.length(); ++i) {
        if ((s1[k + i] - '0') + (s2[i] - '0') > 3) {
            return false;
        }
    }
    return true;
}

size_t Cut(const string& s1, const string& s2) {
    int k = 0;
    while (!IsValid(k, s1, s2)) {
        ++k;
    }
    return max(s1.length(), s2.length() + k);
}

int main() {
    string bottom, top;
    while (cin >> bottom >> top) {
        cout << min(Cut(bottom, top), Cut(top, bottom)) << endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>// Time:  O(n * k), k is length of the common prefix
// Space: O(1)

// BFS
class Solution {
public:
    /**
     * @param strs: A list of strings
     * @return: The longest common prefix
     */
    string longestCommonPrefix(vector<string> &strs) {
        if (strs.empty()) {
            return "";
        }

        for (int i = 0; i < strs[0].length(); ++i) {
            for (const auto& str : strs) {
                if (i >= str.length() || str[i] != strs[0][i]) {
                    return strs[0].substr(0, i);
                }
            }
        }
        return strs[0];
    }
};

// Time:  O(n * l), l is the max length of strings
// Space: O(1)

// DFS
class Solution2 {
public:
    /**
     * @param strs: A list of strings
     * @return: The longest common prefix
     */
    string longestCommonPrefix(vector<string> &strs) {
        if (strs.empty()) {
            return "";
        }

        auto prefix_len = strs[0].length();
        for (const auto& str : strs) {
            auto i = 0;
            for (; i < str.length() && i < prefix_len && str[i] == strs[0][i]; ++i);
            if (i < prefix_len) {
                prefix_len = i;
            }
        }
        return strs[0].substr(0, prefix_len);
    }
};
<commit_msg>Update longest-common-prefix.cpp<commit_after>// Time:  O(n * k), k is the length of the common prefix
// Space: O(1)

// BFS
class Solution {
public:
    /**
     * @param strs: A list of strings
     * @return: The longest common prefix
     */
    string longestCommonPrefix(vector<string> &strs) {
        if (strs.empty()) {
            return "";
        }

        for (int i = 0; i < strs[0].length(); ++i) {
            for (const auto& str : strs) {
                if (i >= str.length() || str[i] != strs[0][i]) {
                    return strs[0].substr(0, i);
                }
            }
        }
        return strs[0];
    }
};

// Time:  O(n * l), l is the max length of strings
// Space: O(1)

// DFS
class Solution2 {
public:
    /**
     * @param strs: A list of strings
     * @return: The longest common prefix
     */
    string longestCommonPrefix(vector<string> &strs) {
        if (strs.empty()) {
            return "";
        }

        auto prefix_len = strs[0].length();
        for (const auto& str : strs) {
            auto i = 0;
            for (; i < str.length() && i < prefix_len && str[i] == strs[0][i]; ++i);
            if (i < prefix_len) {
                prefix_len = i;
            }
        }
        return strs[0].substr(0, prefix_len);
    }
};
<|endoftext|>


<commit_before>// Time:  O(N * m * n)
// Space: O(m * n)

class Solution {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        const auto M = 1000000000 + 7;
        vector<vector<vector<int>>> dp(2, vector<vector<int>>(m, vector<int>(n)));
        for (int moves = 0; moves < N; ++moves) {
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    dp[(moves + 1) % 2][i][j] = (((i == 0 ? 1 : dp[moves % 2][i - 1][j]) +
                                                  (i == m - 1 ? 1 : dp[moves % 2][i + 1][j])) % M +
                                                 ((j == 0 ? 1 : dp[moves % 2][i][j - 1]) +
                                                  (j == n - 1 ? 1 : dp[moves % 2][i][j + 1])) % M) % M;
                }
            }
        }
        return dp[N % 2][i][j];
    }
};
<commit_msg>Update out-of-boundary-paths.cpp<commit_after>// Time:  O(N * m * n)
// Space: O(m * n)

class Solution {
public:
    int findPaths(int m, int n, int N, int x, int y) {
        const auto M = 1000000000 + 7;
        vector<vector<vector<int>>> dp(2, vector<vector<int>>(m, vector<int>(n)));
        int result = 0;
        for (int moves = 0; moves < N; ++moves) {
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    dp[(moves + 1) % 2][i][j] = (((i == 0 ? 1 : dp[moves % 2][i - 1][j]) +
                                                  (i == m - 1 ? 1 : dp[moves % 2][i + 1][j])) % M +
                                                 ((j == 0 ? 1 : dp[moves % 2][i][j - 1]) +
                                                  (j == n - 1 ? 1 : dp[moves % 2][i][j + 1])) % M) % M;
                }
            }
        }
        return dp[N % 2][x][y];
    }
};
<|endoftext|>