<commit_before>#include <QFont>
#include <QFontDialog>
#include <QKeyEvent>
#include <QObject>
#include <QSettings>

#include <PreferencesWindow.hh>
#include <config.hh>

#include <ui_PreferencesWindow.h>

PreferencesWindow::PreferencesWindow(QWidget *parent, Qt::WindowFlags f)
:
QWidget(parent, f),
d_ui(QSharedPointer<Ui::PreferencesWindow>(new Ui::PreferencesWindow))
{
    d_ui->setupUi(this);

#ifndef USE_REMOTE_CORPUS
    d_ui->groupBox_x->hide();
#endif

#ifndef __APPLE__
    applyAppFont();

    connect(d_ui->appFontPushButton, SIGNAL(clicked()),
        SLOT(selectAppFont()));
#else
    d_ui->tabWidget->removeTab(0);
#endif

    loadColorsTab();
    loadNetworkTab();
    loadRemoteTab();

    connect(d_ui->treeActiveNodeForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->treeActiveNodeBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->keywordsInContextKeywordForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextKeywordBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextContextForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextContextBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->completeSentencesBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->archiveBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveArchiveBaseUrl()));

    connect(d_ui->remoteBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveRemoteBaseUrl()));

    connect(d_ui->webserviceBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveWebserviceBaseUrl()));

    connect(d_ui->restoreDefaultColorsButton, SIGNAL(clicked()),
        SLOT(restoreDefaultColors()));

    connect(d_ui->restoreDefaultNetworkButton, SIGNAL(clicked()),
        SLOT(restoreDefaultNetwork()));

    connect(d_ui->restoreDefaultRemoteButton, SIGNAL(clicked()),
        SLOT(restoreDefaultRemote()));

    connect(d_ui->restoreDefaultWebserviceButton, SIGNAL(clicked()),
        SLOT(restoreDefaultWebservice()));
}

PreferencesWindow::~PreferencesWindow() {}

void PreferencesWindow::applyAppFont()
{
    d_ui->appFontLineEdit->setText(qApp->font().family());
}

void PreferencesWindow::selectAppFont()
{
    bool ok;
    QFont newFont(QFontDialog::getFont(&ok, qApp->font(), this));
    if (!ok)
        return;

    qApp->setFont(newFont);

    QSettings().setValue("appFont", newFont.toString());

    applyAppFont();
}

void PreferencesWindow::loadColorsTab()
{
    QSettings settings;

    settings.beginGroup("Tree");

    d_ui->treeActiveNodeForegroundColor->setColor(
        settings.value("activeNodeForeground", QColor(Qt::white)).value<QColor>());

    d_ui->treeActiveNodeBackgroundColor->setColor(
        settings.value("activeNodeBackground", QColor(Qt::darkGreen)).value<QColor>());

    settings.endGroup();

    settings.beginGroup("KeywordsInContext");

    d_ui->keywordsInContextKeywordForegroundColor->setColor(
        settings.value("keywordForeground", QColor(Qt::black)).value<QColor>());

    d_ui->keywordsInContextKeywordBackgroundColor->setColor(
        settings.value("keywordBackground", QColor(Qt::white)).value<QColor>());

    d_ui->keywordsInContextContextForegroundColor->setColor(
        settings.value("contextForeground", QColor(Qt::darkGray)).value<QColor>());

    d_ui->keywordsInContextContextBackgroundColor->setColor(
        settings.value("contextBackground", QColor(Qt::white)).value<QColor>());

    settings.endGroup();

    settings.beginGroup("CompleteSentence");

    d_ui->completeSentencesBackgroundColor->setColor(
           settings.value("background", QColor(Qt::green)).value<QColor>());

    settings.endGroup();
}

void PreferencesWindow::loadNetworkTab()
{
    QSettings settings;
    d_ui->archiveBaseUrlLineEdit->setText(
        settings.value(ARCHIVE_BASEURL_KEY, DEFAULT_ARCHIVE_BASEURL).toString());

    d_ui->webserviceBaseUrlLineEdit->setText(
        settings.value(WEBSERVICE_BASEURL_KEY, DEFAULT_WEBSERVICE_BASEURL).toString());
}

void PreferencesWindow::loadRemoteTab()
{
    QSettings settings;
    d_ui->remoteBaseUrlLineEdit->setText(
        settings.value(REMOTE_BASEURL_KEY, DEFAULT_REMOTE_BASEURL).toString());
}

void PreferencesWindow::saveArchiveBaseUrl()
{
    QSettings settings;
    settings.setValue(ARCHIVE_BASEURL_KEY, d_ui->archiveBaseUrlLineEdit->text());
}

void PreferencesWindow::saveRemoteBaseUrl()
{
    QSettings settings;
    settings.setValue(REMOTE_BASEURL_KEY, d_ui->remoteBaseUrlLineEdit->text());
}

void PreferencesWindow::saveWebserviceBaseUrl()
{
    QSettings settings;
    settings.setValue(WEBSERVICE_BASEURL_KEY, d_ui->webserviceBaseUrlLineEdit->text());
}

void PreferencesWindow::saveColorsTab()
{
    QSettings settings;

    settings.beginGroup("Tree");
    settings.setValue("activeNodeForeground", d_ui->treeActiveNodeForegroundColor->color());
    settings.setValue("activeNodeBackground", d_ui->treeActiveNodeBackgroundColor->color());
    settings.endGroup();

    settings.beginGroup("KeywordsInContext");
    settings.setValue("keywordForeground", d_ui->keywordsInContextKeywordForegroundColor->color());
    settings.setValue("keywordBackground", d_ui->keywordsInContextKeywordBackgroundColor->color());
    settings.setValue("contextForeground", d_ui->keywordsInContextContextForegroundColor->color());
    settings.setValue("contextBackground", d_ui->keywordsInContextContextBackgroundColor->color());
    settings.endGroup();

    settings.beginGroup("CompleteSentence");
    settings.setValue("background", d_ui->completeSentencesBackgroundColor->color());
    settings.endGroup();
}

void PreferencesWindow::restoreDefaultColors()
{
    QSettings settings;

    settings.beginGroup("Tree");
    settings.remove("");
    settings.endGroup();

    settings.beginGroup("KeywordsInContext");
    settings.remove("");
    settings.endGroup();

    settings.beginGroup("CompleteSentence");
    settings.remove("");
    settings.endGroup();

    loadColorsTab();
}

void PreferencesWindow::restoreDefaultNetwork()
{
    QSettings settings;

    settings.remove(ARCHIVE_BASEURL_KEY);

    loadNetworkTab();
}

void PreferencesWindow::restoreDefaultRemote()
{
    QSettings settings;

    settings.remove(REMOTE_BASEURL_KEY);

    loadRemoteTab();
}

void PreferencesWindow::restoreDefaultWebservice()
{
    QSettings settings;

    settings.remove(WEBSERVICE_BASEURL_KEY);

    loadNetworkTab();
}

void PreferencesWindow::keyPressEvent(QKeyEvent *event)
{
    // Cmd + w closes the window in OS X (and in some programs on Windows as well)
    // But closing preference windows with ESC isn't uncommon either.
    if (event->key() == Qt::Key_Escape
        || (event->key() == Qt::Key_W && event->modifiers() == Qt::ControlModifier))
    {
        hide();
        event->accept();
    }
    else
        QWidget::keyPressEvent(event);
}
<commit_msg>Also hide webserivce preferences when webservice client is disabled #82<commit_after>#include <QFont>
#include <QFontDialog>
#include <QKeyEvent>
#include <QObject>
#include <QSettings>

#include <PreferencesWindow.hh>
#include <config.hh>

#include <ui_PreferencesWindow.h>

PreferencesWindow::PreferencesWindow(QWidget *parent, Qt::WindowFlags f)
:
QWidget(parent, f),
d_ui(QSharedPointer<Ui::PreferencesWindow>(new Ui::PreferencesWindow))
{
    d_ui->setupUi(this);

#ifndef USE_REMOTE_CORPUS
    d_ui->groupBox_x->hide();
#endif

#ifndef USE_WEBSERVICE
    d_ui->groupBoxWebservice->hide();
#endif

#ifndef __APPLE__
    applyAppFont();

    connect(d_ui->appFontPushButton, SIGNAL(clicked()),
        SLOT(selectAppFont()));
#else
    d_ui->tabWidget->removeTab(0);
#endif

    loadColorsTab();
    loadNetworkTab();
    loadRemoteTab();

    connect(d_ui->treeActiveNodeForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->treeActiveNodeBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->keywordsInContextKeywordForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextKeywordBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextContextForegroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));
    connect(d_ui->keywordsInContextContextBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->completeSentencesBackgroundColor, SIGNAL(colorSelected(QColor)),
        SLOT(saveColorsTab()));

    connect(d_ui->archiveBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveArchiveBaseUrl()));

    connect(d_ui->remoteBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveRemoteBaseUrl()));

    connect(d_ui->webserviceBaseUrlLineEdit, SIGNAL(editingFinished()),
        SLOT(saveWebserviceBaseUrl()));

    connect(d_ui->restoreDefaultColorsButton, SIGNAL(clicked()),
        SLOT(restoreDefaultColors()));

    connect(d_ui->restoreDefaultNetworkButton, SIGNAL(clicked()),
        SLOT(restoreDefaultNetwork()));

    connect(d_ui->restoreDefaultRemoteButton, SIGNAL(clicked()),
        SLOT(restoreDefaultRemote()));

    connect(d_ui->restoreDefaultWebserviceButton, SIGNAL(clicked()),
        SLOT(restoreDefaultWebservice()));
}

PreferencesWindow::~PreferencesWindow() {}

void PreferencesWindow::applyAppFont()
{
    d_ui->appFontLineEdit->setText(qApp->font().family());
}

void PreferencesWindow::selectAppFont()
{
    bool ok;
    QFont newFont(QFontDialog::getFont(&ok, qApp->font(), this));
    if (!ok)
        return;

    qApp->setFont(newFont);

    QSettings().setValue("appFont", newFont.toString());

    applyAppFont();
}

void PreferencesWindow::loadColorsTab()
{
    QSettings settings;

    settings.beginGroup("Tree");

    d_ui->treeActiveNodeForegroundColor->setColor(
        settings.value("activeNodeForeground", QColor(Qt::white)).value<QColor>());

    d_ui->treeActiveNodeBackgroundColor->setColor(
        settings.value("activeNodeBackground", QColor(Qt::darkGreen)).value<QColor>());

    settings.endGroup();

    settings.beginGroup("KeywordsInContext");

    d_ui->keywordsInContextKeywordForegroundColor->setColor(
        settings.value("keywordForeground", QColor(Qt::black)).value<QColor>());

    d_ui->keywordsInContextKeywordBackgroundColor->setColor(
        settings.value("keywordBackground", QColor(Qt::white)).value<QColor>());

    d_ui->keywordsInContextContextForegroundColor->setColor(
        settings.value("contextForeground", QColor(Qt::darkGray)).value<QColor>());

    d_ui->keywordsInContextContextBackgroundColor->setColor(
        settings.value("contextBackground", QColor(Qt::white)).value<QColor>());

    settings.endGroup();

    settings.beginGroup("CompleteSentence");

    d_ui->completeSentencesBackgroundColor->setColor(
           settings.value("background", QColor(Qt::green)).value<QColor>());

    settings.endGroup();
}

void PreferencesWindow::loadNetworkTab()
{
    QSettings settings;
    d_ui->archiveBaseUrlLineEdit->setText(
        settings.value(ARCHIVE_BASEURL_KEY, DEFAULT_ARCHIVE_BASEURL).toString());

    d_ui->webserviceBaseUrlLineEdit->setText(
        settings.value(WEBSERVICE_BASEURL_KEY, DEFAULT_WEBSERVICE_BASEURL).toString());
}

void PreferencesWindow::loadRemoteTab()
{
    QSettings settings;
    d_ui->remoteBaseUrlLineEdit->setText(
        settings.value(REMOTE_BASEURL_KEY, DEFAULT_REMOTE_BASEURL).toString());
}

void PreferencesWindow::saveArchiveBaseUrl()
{
    QSettings settings;
    settings.setValue(ARCHIVE_BASEURL_KEY, d_ui->archiveBaseUrlLineEdit->text());
}

void PreferencesWindow::saveRemoteBaseUrl()
{
    QSettings settings;
    settings.setValue(REMOTE_BASEURL_KEY, d_ui->remoteBaseUrlLineEdit->text());
}

void PreferencesWindow::saveWebserviceBaseUrl()
{
    QSettings settings;
    settings.setValue(WEBSERVICE_BASEURL_KEY, d_ui->webserviceBaseUrlLineEdit->text());
}

void PreferencesWindow::saveColorsTab()
{
    QSettings settings;

    settings.beginGroup("Tree");
    settings.setValue("activeNodeForeground", d_ui->treeActiveNodeForegroundColor->color());
    settings.setValue("activeNodeBackground", d_ui->treeActiveNodeBackgroundColor->color());
    settings.endGroup();

    settings.beginGroup("KeywordsInContext");
    settings.setValue("keywordForeground", d_ui->keywordsInContextKeywordForegroundColor->color());
    settings.setValue("keywordBackground", d_ui->keywordsInContextKeywordBackgroundColor->color());
    settings.setValue("contextForeground", d_ui->keywordsInContextContextForegroundColor->color());
    settings.setValue("contextBackground", d_ui->keywordsInContextContextBackgroundColor->color());
    settings.endGroup();

    settings.beginGroup("CompleteSentence");
    settings.setValue("background", d_ui->completeSentencesBackgroundColor->color());
    settings.endGroup();
}

void PreferencesWindow::restoreDefaultColors()
{
    QSettings settings;

    settings.beginGroup("Tree");
    settings.remove("");
    settings.endGroup();

    settings.beginGroup("KeywordsInContext");
    settings.remove("");
    settings.endGroup();

    settings.beginGroup("CompleteSentence");
    settings.remove("");
    settings.endGroup();

    loadColorsTab();
}

void PreferencesWindow::restoreDefaultNetwork()
{
    QSettings settings;

    settings.remove(ARCHIVE_BASEURL_KEY);

    loadNetworkTab();
}

void PreferencesWindow::restoreDefaultRemote()
{
    QSettings settings;

    settings.remove(REMOTE_BASEURL_KEY);

    loadRemoteTab();
}

void PreferencesWindow::restoreDefaultWebservice()
{
    QSettings settings;

    settings.remove(WEBSERVICE_BASEURL_KEY);

    loadNetworkTab();
}

void PreferencesWindow::keyPressEvent(QKeyEvent *event)
{
    // Cmd + w closes the window in OS X (and in some programs on Windows as well)
    // But closing preference windows with ESC isn't uncommon either.
    if (event->key() == Qt::Key_Escape
        || (event->key() == Qt::Key_W && event->modifiers() == Qt::ControlModifier))
    {
        hide();
        event->accept();
    }
    else
        QWidget::keyPressEvent(event);
}
<|endoftext|>


<commit_before>
#include <iostream>

#ifdef __cplusplus
extern "C"
{
#endif

int xerbla_(const char * msg, int *info, int)
{
  std::cerr << "Eigen BLAS ERROR #" << *info << ": " << msg << "\n";
  return 0;
}

#ifdef __cplusplus
}
#endif
<commit_msg>enforce weak linking of xerbla<commit_after>
#include <iostream>

#if (defined __GNUC__)
#define EIGEN_WEAK_LINKING __attribute__ ((weak))
#else
#define EIGEN_WEAK_LINKING
#endif

#ifdef __cplusplus
extern "C"
{
#endif

EIGEN_WEAK_LINKING int xerbla_(const char * msg, int *info, int)
{
  std::cerr << "Eigen BLAS ERROR #" << *info << ": " << msg << "\n";
  return 0;
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>
#include "PuzzlesDrawingApi.h"
#include "CGameView.h"
#include "CGameContainer.h"

extern "C" {
#include "puzzles.h"
}

void CPuzzlesDrawingApi::DrawAPI_DrawText(void *handle, int x, int y, int fonttype,
    int fontsize, int align, int colour, char *text) {
    ((CGameView*) handle)->DrawText(x, y, fonttype, fontsize, align, colour, text);
}
void CPuzzlesDrawingApi::DrawAPI_DrawRect(void *handle, int x, int y, int w, int h, int colour) {
    ((CGameView*) handle)->DrawRect(x, y, w, h, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawLine(void *handle, int x1, int y1, int x2, int y2, int colour) {
    ((CGameView*) handle)->DrawLine(x1, y1, x2, y2, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawThickLine(void *handle, float thickness, float x1,
    float y1, float x2, float y2, int colour) {
    ((CGameView*) handle)->DrawThickLine(thickness, x1, y1, x2, y2, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawPolygon(void *handle, int *coords, int npoints,
    int fillcolour, int outlinecolour) {
    ((CGameView*) handle)->DrawPolygon(
        coords, npoints, fillcolour, outlinecolour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawCircle(void *handle, int cx, int cy, int radius,
    int fillcolour, int outlinecolour) {
    ((CGameView*) handle)->DrawCircle(cx, cy, radius, fillcolour, outlinecolour);
}
void CPuzzlesDrawingApi::DrawAPI_Clip(void *handle, int x, int y, int w, int h) {
    ((CGameView*) handle)->Clip(x, y, w, h);
}
void CPuzzlesDrawingApi::DrawAPI_Unclip(void *handle) {
    ((CGameView*)handle)->Unclip();
}
void CPuzzlesDrawingApi::DrawAPI_StartDraw(void *handle) {
    ((CGameView*) handle)->StartDraw();
}
void CPuzzlesDrawingApi::DrawAPI_DrawUpdate(void *handle, int x, int y, int w, int h) {
    ((CGameView*) handle)->DrawUpdate(x, y, w, h);
}
void CPuzzlesDrawingApi::DrawAPI_EndDraw(void *handle) {
    ((CGameView*) handle)->EndDraw();
}
blitter *CPuzzlesDrawingApi::DrawAPI_BlitterNew(void *handle, int w, int h) {
    return ((CGameView*) handle)->BlitterNew(w, h);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterFree(void *handle, blitter *bl) {
    ((CGameView*) handle)->BlitterFree(bl);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterSave(void *handle, blitter *bl, int x, int y) {
    ((CGameView*) handle)->BlitterSave(bl, x, y);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterLoad(void *handle, blitter *bl, int x, int y) {
    ((CGameView*) handle)->BlitterLoad(bl, x, y);
}
void CPuzzlesDrawingApi::DrawAPI_StatusBar(void *handle, char *text) {
    TPtrC8 pText((TUint8*)text);
    TBuf<100> buf;
    buf.Copy(pText);
    ((CGameView*) handle)->iGameContainer->SetStatusText(buf);
}

const drawing_api *CPuzzlesDrawingApi::Api() {
    static const struct drawing_api drawing_api = {
        DrawAPI_DrawText,
        DrawAPI_DrawRect,
        DrawAPI_DrawLine,
        DrawAPI_DrawPolygon,
        DrawAPI_DrawCircle,
        DrawAPI_DrawUpdate,
        DrawAPI_Clip,
        DrawAPI_Unclip,
        DrawAPI_StartDraw,
        DrawAPI_EndDraw,
        DrawAPI_StatusBar,
        DrawAPI_BlitterNew,
        DrawAPI_BlitterFree,
        DrawAPI_BlitterSave,
        DrawAPI_BlitterLoad,

        NULL, // begin_doc
        NULL, // begin_page
        NULL, // begin_puzzle
        NULL, // end_puzzle
        NULL, // end_page
        NULL, // end_doc
        NULL, // line_width
        NULL, // line_dotted
        NULL, // text_fallback

        DrawAPI_DrawThickLine,
    };
    return &drawing_api;
}
<commit_msg>the 'improvement' to drawing thick lines wasn't an improvement at all... use the default implementation instead<commit_after>
#include "PuzzlesDrawingApi.h"
#include "CGameView.h"
#include "CGameContainer.h"

extern "C" {
#include "puzzles.h"
}

void CPuzzlesDrawingApi::DrawAPI_DrawText(void *handle, int x, int y, int fonttype,
    int fontsize, int align, int colour, char *text) {
    ((CGameView*) handle)->DrawText(x, y, fonttype, fontsize, align, colour, text);
}
void CPuzzlesDrawingApi::DrawAPI_DrawRect(void *handle, int x, int y, int w, int h, int colour) {
    ((CGameView*) handle)->DrawRect(x, y, w, h, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawLine(void *handle, int x1, int y1, int x2, int y2, int colour) {
    ((CGameView*) handle)->DrawLine(x1, y1, x2, y2, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawThickLine(void *handle, float thickness, float x1,
    float y1, float x2, float y2, int colour) {
    ((CGameView*) handle)->DrawThickLine(thickness, x1, y1, x2, y2, colour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawPolygon(void *handle, int *coords, int npoints,
    int fillcolour, int outlinecolour) {
    ((CGameView*) handle)->DrawPolygon(
        coords, npoints, fillcolour, outlinecolour);
}
void CPuzzlesDrawingApi::DrawAPI_DrawCircle(void *handle, int cx, int cy, int radius,
    int fillcolour, int outlinecolour) {
    ((CGameView*) handle)->DrawCircle(cx, cy, radius, fillcolour, outlinecolour);
}
void CPuzzlesDrawingApi::DrawAPI_Clip(void *handle, int x, int y, int w, int h) {
    ((CGameView*) handle)->Clip(x, y, w, h);
}
void CPuzzlesDrawingApi::DrawAPI_Unclip(void *handle) {
    ((CGameView*)handle)->Unclip();
}
void CPuzzlesDrawingApi::DrawAPI_StartDraw(void *handle) {
    ((CGameView*) handle)->StartDraw();
}
void CPuzzlesDrawingApi::DrawAPI_DrawUpdate(void *handle, int x, int y, int w, int h) {
    ((CGameView*) handle)->DrawUpdate(x, y, w, h);
}
void CPuzzlesDrawingApi::DrawAPI_EndDraw(void *handle) {
    ((CGameView*) handle)->EndDraw();
}
blitter *CPuzzlesDrawingApi::DrawAPI_BlitterNew(void *handle, int w, int h) {
    return ((CGameView*) handle)->BlitterNew(w, h);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterFree(void *handle, blitter *bl) {
    ((CGameView*) handle)->BlitterFree(bl);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterSave(void *handle, blitter *bl, int x, int y) {
    ((CGameView*) handle)->BlitterSave(bl, x, y);
}
void CPuzzlesDrawingApi::DrawAPI_BlitterLoad(void *handle, blitter *bl, int x, int y) {
    ((CGameView*) handle)->BlitterLoad(bl, x, y);
}
void CPuzzlesDrawingApi::DrawAPI_StatusBar(void *handle, char *text) {
    TPtrC8 pText((TUint8*)text);
    TBuf<100> buf;
    buf.Copy(pText);
    ((CGameView*) handle)->iGameContainer->SetStatusText(buf);
}

const drawing_api *CPuzzlesDrawingApi::Api() {
    static const struct drawing_api drawing_api = {
        DrawAPI_DrawText,
        DrawAPI_DrawRect,
        DrawAPI_DrawLine,
        DrawAPI_DrawPolygon,
        DrawAPI_DrawCircle,
        DrawAPI_DrawUpdate,
        DrawAPI_Clip,
        DrawAPI_Unclip,
        DrawAPI_StartDraw,
        DrawAPI_EndDraw,
        DrawAPI_StatusBar,
        DrawAPI_BlitterNew,
        DrawAPI_BlitterFree,
        DrawAPI_BlitterSave,
        DrawAPI_BlitterLoad,

        NULL, // begin_doc
        NULL, // begin_page
        NULL, // begin_puzzle
        NULL, // end_puzzle
        NULL, // end_page
        NULL, // end_doc
        NULL, // line_width
        NULL, // line_dotted
        NULL, // text_fallback

        NULL, // DrawAPI_DrawThickLine,
    };
    return &drawing_api;
}
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <gdgem/srs/ParserVMM3.h>
#include <gdgem/srs/ParserVMM3TestData.h>
#include <test/TestBase.h>
#include <vector>

using namespace Gem;

class ParserVMM3Test : public TestBase {

protected:
  NMXStats stats;
  ParserVMM3 *parser;
  SRSTime srsTime;
  void SetUp() override {
    srsTime.bc_clock_MHz(40);
    srsTime.tac_slope_ns(60);
    srsTime.trigger_resolution_ns(1);
    parser = new ParserVMM3(1125, stats, srsTime);
  }
  void TearDown() override { delete parser; }

  void memSet() {
    parser->stats.parser_readouts = 0;
    parser->stats.parser_data = 0;
    parser->stats.parser_markers = 0;
    parser->stats.parser_frame_missing_errors = 0;
    parser->stats.parser_frame_seq_errors = 0;
    parser->stats.parser_framecounter_overflows = 0;
    parser->stats.parser_timestamp_lost_errors = 0;
    parser->stats.parser_timestamp_seq_errors = 0;
    parser->stats.parser_timestamp_overflows = 0;
    parser->stats.parser_bad_frames = 0;
    parser->stats.parser_good_frames = 0;
    parser->stats.parser_error_bytes = 0;
  }

  void assertfields(unsigned int hits, unsigned int markers, unsigned int errors) {
    EXPECT_EQ(parser->stats.parser_data, hits);
    EXPECT_EQ(parser->stats.parser_markers, markers);
    EXPECT_EQ(parser->stats.parser_error_bytes, errors);
  }
};

/** Test cases below */
TEST_F(ParserVMM3Test, Constructor) {
  EXPECT_TRUE(parser->data != nullptr);
  assertfields(0, 0, 0);
  for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
    EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
  }
}

TEST_F(ParserVMM3Test, UndersizeData) {
  for (int dataLength = 0; dataLength <= 16; dataLength++) {
    memSet();
    int res = parser->receive((char *)&data_3_ch0[0], dataLength);
    EXPECT_EQ(res, 0);
    assertfields(0, 0, dataLength);
    for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
      EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
    }
  }
}

TEST_F(ParserVMM3Test, DataOnly) {
  memSet();
  int res = parser->receive((char *)&data_3_ch0[0], data_3_ch0.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 0, 0);
  for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
    EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
  }
}

TEST_F(ParserVMM3Test, MarkerOnly) {
  memSet();
  int res = parser->receive((char *)&marker_3_vmm1_3[0], marker_3_vmm1_3.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, TimestampError) {
  memSet();
  int res = parser->receive((char *)&timestamp_error[0], timestamp_error.size());
  EXPECT_EQ(res, 0);
  EXPECT_EQ(0, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_seq_errors);
}

TEST_F(ParserVMM3Test, TimestampOverflow) {
  memSet();
  int res = parser->receive((char *)&timestamp_overflow[0], timestamp_overflow.size());
  EXPECT_EQ(res, 0);
  EXPECT_EQ(0, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_overflows);
}

TEST_F(ParserVMM3Test, TimestampLost) {
  memSet();
  int res = parser->receive((char *)&timestamp_lost[0], timestamp_lost.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, parser->stats.parser_data);
  EXPECT_EQ(1, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_lost_errors);
}

TEST_F(ParserVMM3Test, TimestampNotLost) {
  memSet();
  int res = parser->receive((char *)&timestamp_not_lost[0], timestamp_not_lost.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(0, parser->stats.parser_timestamp_lost_errors);
}

TEST_F(ParserVMM3Test, FrameMissingError) {
  memSet();
  int res = parser->receive((char *)&framecounter_error1[0], framecounter_error1.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_error2[0], framecounter_error2.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(2, parser->stats.parser_frame_missing_errors);
}

TEST_F(ParserVMM3Test, FrameOrderError) {
  memSet();
  int res = parser->receive((char *)&framecounter_error2[0], framecounter_error2.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_error1[0], framecounter_error1.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(1, parser->stats.parser_frame_seq_errors);
}

TEST_F(ParserVMM3Test, FramecounterOverflow) {
  memSet();
  int res = parser->receive((char *)&framecounter_overflow1[0], framecounter_overflow1.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_overflow2[0], framecounter_overflow2.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(1, parser->stats.parser_framecounter_overflows);
}

TEST_F(ParserVMM3Test, MarkerAndData) {
  memSet();
  int res = parser->receive((char *)&marker_3_data_3[0], marker_3_data_3.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, MarkerAndDataMixed) {
  memSet();
  int res = parser->receive((char *)&marker_data_mixed_3[0], marker_data_mixed_3.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, NoData) {
  memSet();
  int res = parser->receive((char *)&no_data[0], no_data.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, no_data.size());
}

TEST_F(ParserVMM3Test, InvalidDataId) {
  memSet();
  int res = parser->receive((char *)&invalid_dataid[0], invalid_dataid.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, invalid_dataid.size());
}

TEST_F(ParserVMM3Test, InconsistentDataLength) {
  memSet();
  int res = parser->receive((char *)&inconsistent_datalen[0], inconsistent_datalen.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, inconsistent_datalen.size());
}

TEST_F(ParserVMM3Test, DataLengthOverflow) {
  NMXStats stats;
  SRSTime srsTime;
  srsTime.bc_clock_MHz(40);
  srsTime.tac_slope_ns(60);
  srsTime.trigger_resolution_ns(1);
  ParserVMM3 shortvmmbuffer(2,stats, srsTime);
  int res = shortvmmbuffer.receive((char *)& data_3_ch0[0],  data_3_ch0.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, shortvmmbuffer.stats.parser_data);
  EXPECT_EQ(0, shortvmmbuffer.stats.parser_markers);
  EXPECT_EQ(6, shortvmmbuffer.stats.parser_error_bytes);
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Removal of new.<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <gdgem/srs/ParserVMM3.h>
#include <gdgem/srs/ParserVMM3TestData.h>
#include <test/TestBase.h>
#include <vector>

using namespace Gem;

class ParserVMM3Test : public TestBase {

protected:
  NMXStats stats;
  std::unique_ptr<ParserVMM3> parser;
  SRSTime srsTime;
  void SetUp() override {
    srsTime.bc_clock_MHz(40);
    srsTime.tac_slope_ns(60);
    srsTime.trigger_resolution_ns(1);
    parser = std::make_unique<ParserVMM3>(1125, stats, srsTime);
  }

  void memSet() {
    parser->stats.parser_readouts = 0;
    parser->stats.parser_data = 0;
    parser->stats.parser_markers = 0;
    parser->stats.parser_frame_missing_errors = 0;
    parser->stats.parser_frame_seq_errors = 0;
    parser->stats.parser_framecounter_overflows = 0;
    parser->stats.parser_timestamp_lost_errors = 0;
    parser->stats.parser_timestamp_seq_errors = 0;
    parser->stats.parser_timestamp_overflows = 0;
    parser->stats.parser_bad_frames = 0;
    parser->stats.parser_good_frames = 0;
    parser->stats.parser_error_bytes = 0;
  }

  void assertfields(unsigned int hits, unsigned int markers, unsigned int errors) {
    EXPECT_EQ(parser->stats.parser_data, hits);
    EXPECT_EQ(parser->stats.parser_markers, markers);
    EXPECT_EQ(parser->stats.parser_error_bytes, errors);
  }
};

/** Test cases below */
TEST_F(ParserVMM3Test, Constructor) {
  EXPECT_TRUE(parser->data != nullptr);
  assertfields(0, 0, 0);
  for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
    EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
  }
}

TEST_F(ParserVMM3Test, UndersizeData) {
  for (int dataLength = 0; dataLength <= 16; dataLength++) {
    memSet();
    int res = parser->receive((char *)&data_3_ch0[0], dataLength);
    EXPECT_EQ(res, 0);
    assertfields(0, 0, dataLength);
    for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
      EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
    }
  }
}

TEST_F(ParserVMM3Test, DataOnly) {
  memSet();
  int res = parser->receive((char *)&data_3_ch0[0], data_3_ch0.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 0, 0);
  for (int i = 0; i < MaxVMMs*MaxFECs; i++) {
    EXPECT_EQ(parser->markers[i].fecTimeStamp, 0U);
  }
}

TEST_F(ParserVMM3Test, MarkerOnly) {
  memSet();
  int res = parser->receive((char *)&marker_3_vmm1_3[0], marker_3_vmm1_3.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, TimestampError) {
  memSet();
  int res = parser->receive((char *)&timestamp_error[0], timestamp_error.size());
  EXPECT_EQ(res, 0);
  EXPECT_EQ(0, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_seq_errors);
}

TEST_F(ParserVMM3Test, TimestampOverflow) {
  memSet();
  int res = parser->receive((char *)&timestamp_overflow[0], timestamp_overflow.size());
  EXPECT_EQ(res, 0);
  EXPECT_EQ(0, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_overflows);
}

TEST_F(ParserVMM3Test, TimestampLost) {
  memSet();
  int res = parser->receive((char *)&timestamp_lost[0], timestamp_lost.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, parser->stats.parser_data);
  EXPECT_EQ(1, parser->stats.parser_markers);
  EXPECT_EQ(1, parser->stats.parser_timestamp_lost_errors);
}

TEST_F(ParserVMM3Test, TimestampNotLost) {
  memSet();
  int res = parser->receive((char *)&timestamp_not_lost[0], timestamp_not_lost.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, parser->stats.parser_data);
  EXPECT_EQ(2, parser->stats.parser_markers);
  EXPECT_EQ(0, parser->stats.parser_timestamp_lost_errors);
}

TEST_F(ParserVMM3Test, FrameMissingError) {
  memSet();
  int res = parser->receive((char *)&framecounter_error1[0], framecounter_error1.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_error2[0], framecounter_error2.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(2, parser->stats.parser_frame_missing_errors);
}

TEST_F(ParserVMM3Test, FrameOrderError) {
  memSet();
  int res = parser->receive((char *)&framecounter_error2[0], framecounter_error2.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_error1[0], framecounter_error1.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(1, parser->stats.parser_frame_seq_errors);
}

TEST_F(ParserVMM3Test, FramecounterOverflow) {
  memSet();
  int res = parser->receive((char *)&framecounter_overflow1[0], framecounter_overflow1.size());
  EXPECT_EQ(res, 1);
  res = parser->receive((char *)&framecounter_overflow2[0], framecounter_overflow2.size());
  EXPECT_EQ(res, 1);
  EXPECT_EQ(1, parser->stats.parser_framecounter_overflows);
}

TEST_F(ParserVMM3Test, MarkerAndData) {
  memSet();
  int res = parser->receive((char *)&marker_3_data_3[0], marker_3_data_3.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, MarkerAndDataMixed) {
  memSet();
  int res = parser->receive((char *)&marker_data_mixed_3[0], marker_data_mixed_3.size());
  EXPECT_EQ(res, 3); // three readouts in the readout packet
  assertfields(3, 3, 0);
  for (int i = 0; i < 3; i++) {
    int vmmid = i + 1; // see test data
    EXPECT_EQ(parser->markers[vmmid].fecTimeStamp, i + 1);
  }
}

TEST_F(ParserVMM3Test, NoData) {
  memSet();
  int res = parser->receive((char *)&no_data[0], no_data.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, no_data.size());
}

TEST_F(ParserVMM3Test, InvalidDataId) {
  memSet();
  int res = parser->receive((char *)&invalid_dataid[0], invalid_dataid.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, invalid_dataid.size());
}

TEST_F(ParserVMM3Test, InconsistentDataLength) {
  memSet();
  int res = parser->receive((char *)&inconsistent_datalen[0], inconsistent_datalen.size());
  EXPECT_EQ(res, 0);
  assertfields(0, 0, inconsistent_datalen.size());
}

TEST_F(ParserVMM3Test, DataLengthOverflow) {
  NMXStats stats;
  SRSTime srsTime;
  srsTime.bc_clock_MHz(40);
  srsTime.tac_slope_ns(60);
  srsTime.trigger_resolution_ns(1);
  ParserVMM3 shortvmmbuffer(2,stats, srsTime);
  int res = shortvmmbuffer.receive((char *)& data_3_ch0[0],  data_3_ch0.size());
  EXPECT_EQ(res, 2);
  EXPECT_EQ(2, shortvmmbuffer.stats.parser_data);
  EXPECT_EQ(0, shortvmmbuffer.stats.parser_markers);
  EXPECT_EQ(6, shortvmmbuffer.stats.parser_error_bytes);
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/**
 * @file	src/UI/python/PythonBreaker.cpp
 * @date	Jul. 2016
 * @author	PhRG - opticalp.fr
 */

/*
 Copyright (c) 2016 Ph. Renaud-Goud / Opticalp

 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.
 */

#ifdef HAVE_PYTHON27

#include "PythonBreaker.h"

extern "C" void pyBreakerDealloc(BreakerMembers* self)
{
    delete self->breaker;

    self->ob_type->tp_free((PyObject*) self); // free the object’s memory
}

extern "C" PyObject* pyBreakerNew(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
    BreakerMembers* self;

    self = (BreakerMembers*) type->tp_alloc(type, 0);
    if (self != NULL)
        self->breaker = new Breaker;

    return (PyObject *) self;
}

extern "C" int pyBreakerInit(BreakerMembers* self, PyObject* args, PyObject *kwds)
{
	PyObject pyObj;

	if (!PyArg_ParseTuple(args, "", &pyObj))
		return -1;

	return 0;
}

#include "PythonOutPort.h"

extern "C" PyObject* pyBreakerBreakAllTargets(BreakerMembers* self, PyObject* args)
{
	PyObject *pyObj;

    // arguments parsing
    if (!PyArg_ParseTuple(args, "O:breakAllTargets", &pyObj))
        return NULL;

    // check if the object is a data source
    // the comparison uses type name (str)
    std::string typeName(pyObj->ob_type->tp_name);

    DataSource* source;

    if (typeName.compare("instru.OutPort")) // only data source yet
    {
        PyErr_SetString(PyExc_TypeError,
                "The argument must be a data source (output port)");
        return NULL;
    }
    else
    {
    	source = **reinterpret_cast<OutPortMembers*>(pyObj)->outPort;
    }

    try
    {
    	self->breaker->breakAllTargetsFromSource(source);
    }
    catch (Poco::Exception& e)
    {
        PyErr_SetString(PyExc_RuntimeError,
                e.displayText().c_str());
        return NULL;
    }

    Py_RETURN_NONE;
}

#include "PythonInPort.h"
#include "PythonDataLogger.h"

extern "C" PyObject* pyBreakerBreakSource(BreakerMembers* self, PyObject* args)
{
	PyObject *pyObj;

    // arguments parsing
    if (!PyArg_ParseTuple(args, "O:breakSource", &pyObj))
        return NULL;

    // check if the object is a data target
    // the comparison uses type name (str)
    std::string typeName(pyObj->ob_type->tp_name);

    DataTarget* target;

    if (typeName.compare("instru.InPort") == 0)
    {
    	target = **reinterpret_cast<InPortMembers*>(pyObj)->inPort;
    }
    else if (typeName.compare("instru.DataLogger") == 0)
    {
    	target = *reinterpret_cast<DataLoggerMembers*>(pyObj)->logger;
    }
    else
    {
        PyErr_SetString(PyExc_TypeError,
                "The argument must be a data target (input port or data logger)");
        return NULL;
    }

    try
    {
    	self->breaker->breakSourceToTarget(target);
    }
    catch (Poco::Exception& e)
    {
        PyErr_SetString(PyExc_RuntimeError,
                e.displayText().c_str());
        return NULL;
    }

	Py_RETURN_NONE;
}

extern "C" PyObject* pyBreakerRelease(BreakerMembers* self)
{
	self->breaker->releaseBreaks();

	Py_RETURN_NONE;
}

#endif /* HAVE_PYTHON27 */
<commit_msg>Generalize the breakers to any DataSource or any DataTarget<commit_after>/**
 * @file	src/UI/python/PythonBreaker.cpp
 * @date	Jul. 2016
 * @author	PhRG - opticalp.fr
 */

/*
 Copyright (c) 2016 Ph. Renaud-Goud / Opticalp

 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.
 */

#ifdef HAVE_PYTHON27

#include "PythonBreaker.h"

extern "C" void pyBreakerDealloc(BreakerMembers* self)
{
    delete self->breaker;

    self->ob_type->tp_free((PyObject*) self); // free the object’s memory
}

extern "C" PyObject* pyBreakerNew(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
    BreakerMembers* self;

    self = (BreakerMembers*) type->tp_alloc(type, 0);
    if (self != NULL)
        self->breaker = new Breaker;

    return (PyObject *) self;
}

extern "C" int pyBreakerInit(BreakerMembers* self, PyObject* args, PyObject *kwds)
{
	PyObject pyObj;

	if (!PyArg_ParseTuple(args, "", &pyObj))
		return -1;

	return 0;
}

#include "PythonOutPort.h"
#include "PythonDataSource.h"

extern "C" PyObject* pyBreakerBreakAllTargets(BreakerMembers* self, PyObject* args)
{
	PyObject *pyObj;

    // arguments parsing
    if (!PyArg_ParseTuple(args, "O:breakAllTargets", &pyObj))
        return NULL;

    // check if the object is a data source
    // the comparison uses type name (str)
    std::string typeName(pyObj->ob_type->tp_name);

    DataSource* source;

    if (typeName.compare("instru.OutPort") == 0)
    {
        source = **reinterpret_cast<OutPortMembers*>(pyObj)->outPort;
    }
    else if (typeName.compare("instru.DataSource") == 0)
    {
        DataSourceMembers* pyDataSource = reinterpret_cast<DataSourceMembers*>(pyObj);
        source = pyDataSource->source;
    }
    else
    {
        PyErr_SetString(PyExc_TypeError,
                "The argument must be a data source (output port or DataSource cast)");
        return NULL;
    }

    try
    {
    	self->breaker->breakAllTargetsFromSource(source);
    }
    catch (Poco::Exception& e)
    {
        PyErr_SetString(PyExc_RuntimeError,
                e.displayText().c_str());
        return NULL;
    }

    Py_RETURN_NONE;
}

#include "PythonInPort.h"
#include "PythonDataLogger.h"
#include "PythonDataTarget.h"

extern "C" PyObject* pyBreakerBreakSource(BreakerMembers* self, PyObject* args)
{
	PyObject *pyObj;

    // arguments parsing
    if (!PyArg_ParseTuple(args, "O:breakSource", &pyObj))
        return NULL;

    // check if the object is a data target
    // the comparison uses type name (str)
    std::string typeName(pyObj->ob_type->tp_name);

    DataTarget* target;

    if (typeName.compare("instru.InPort") == 0)
    {
    	target = **reinterpret_cast<InPortMembers*>(pyObj)->inPort;
    }
    else if (typeName.compare("instru.DataLogger") == 0)
    {
    	target = *reinterpret_cast<DataLoggerMembers*>(pyObj)->logger;
    }
    else if (typeName.compare("instru.DataTarget") == 0)
    {
        DataTargetMembers* pyDataTarget = reinterpret_cast<DataTargetMembers*>(pyObj);
        target = pyDataTarget->target;
    }
    else
    {
        PyErr_SetString(PyExc_TypeError,
                "The argument must be a data target (input port, data logger or DataTarget cast)");
        return NULL;
    }

    try
    {
    	self->breaker->breakSourceToTarget(target);
    }
    catch (Poco::Exception& e)
    {
        PyErr_SetString(PyExc_RuntimeError,
                e.displayText().c_str());
        return NULL;
    }

	Py_RETURN_NONE;
}

extern "C" PyObject* pyBreakerRelease(BreakerMembers* self)
{
	self->breaker->releaseBreaks();

	Py_RETURN_NONE;
}

#endif /* HAVE_PYTHON27 */
<|endoftext|>


<commit_before>#include "VideodrommLiveCodingApp.h"

void VideodrommLiveCodingApp::prepare(Settings *settings)
{
	settings->setWindowSize(640, 480);
	//settings->setBorderless();
	settings->setWindowPos(0, 0);
}
void VideodrommLiveCodingApp::setup()
{
	// maximize fps
	disableFrameRate();
	gl::enableVerticalSync(false);
	// Settings
	mVDSettings = VDSettings::create();
	// Session
	mVDSession = VDSession::create(mVDSettings);
	// Utils
	mVDUtils = VDUtils::create(mVDSettings);
	// Animation
	mVDAnimation = VDAnimation::create(mVDSettings, mVDSession);
	// Message router
	mVDRouter = VDRouter::create(mVDSettings, mVDAnimation, mVDSession);
	// Mix
	mMixesFilepath = getAssetPath("") / mVDSettings->mAssetsPath / "mixes.xml";
	if (fs::exists(mMixesFilepath)) {
		// load textures from file if one exists
		mMixes = VDMix::readSettings(mVDSettings, mVDAnimation, mVDRouter, loadFile(mMixesFilepath));
	}
	else {
		// otherwise create a texture from scratch
		mMixes.push_back(VDMix::create(mVDSettings, mVDAnimation, mVDRouter));
	}
	mVDAnimation->tapTempo();

	mVDUtils->getWindowsResolution();
	setWindowSize(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight);

	mVDSettings->iResolution.x = mVDSettings->mRenderWidth;
	mVDSettings->iResolution.y = mVDSettings->mRenderHeight;
	// UI
	mVDUI = VDUI::create(mVDSettings, mMixes[0], mVDRouter, mVDAnimation, mVDSession);

	mouseGlobal = false;

	static float f = 0.0f;
	// mouse cursor and UI
	setUIVisibility(mVDSettings->mCursorVisible);
	// windows
	mIsShutDown = false;
	mIsResizing = true;
	mMainWindow = getWindow();
	mMainWindow->getSignalDraw().connect(std::bind(&VideodrommLiveCodingApp::drawMain, this));
	mMainWindow->getSignalResize().connect(std::bind(&VideodrommLiveCodingApp::resizeWindow, this));
	/*if (mVDSettings->mStandalone) {
		createRenderWindow();
		setWindowSize(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight);
		}
		else {

		}*/
}
void VideodrommLiveCodingApp::createRenderWindow()
{
	deleteRenderWindows();
	mVDUtils->getWindowsResolution();

	mVDSettings->iResolution.x = mVDSettings->mRenderWidth;
	mVDSettings->iResolution.y = mVDSettings->mRenderHeight;

	CI_LOG_V("createRenderWindow, resolution:" + toString(mVDSettings->iResolution.x) + "x" + toString(mVDSettings->iResolution.y));

	string windowName = "render";
	mRenderWindow = createWindow(Window::Format().size(mVDSettings->iResolution.x, mVDSettings->iResolution.y));

	// create instance of the window and store in vector
	allRenderWindows.push_back(mRenderWindow);

	mRenderWindow->setBorderless();
	mRenderWindow->getSignalDraw().connect(std::bind(&VideodrommLiveCodingApp::drawRender, this));
	mVDSettings->mRenderPosXY = ivec2(mVDSettings->mRenderX, mVDSettings->mRenderY);//20141214 was 0
	mRenderWindow->setPos(50, 50);
	mRenderWindowTimer = 0.0f;
	timeline().apply(&mRenderWindowTimer, 1.0f, 2.0f).finishFn([&]{ positionRenderWindow(); });
}
void VideodrommLiveCodingApp::positionRenderWindow()
{
	mRenderWindow->setPos(mVDSettings->mRenderX, mVDSettings->mRenderY);
}
void VideodrommLiveCodingApp::deleteRenderWindows()
{
#if defined( CINDER_MSW )
	for (auto wRef : allRenderWindows) DestroyWindow((HWND)mRenderWindow->getNative());
#endif
	allRenderWindows.clear();
}
void VideodrommLiveCodingApp::setUIVisibility(bool visible)
{
	if (visible)
	{
		showCursor();
	}
	else
	{
		hideCursor();
	}
}
void VideodrommLiveCodingApp::update()
{
	mVDSettings->iFps = getAverageFps();
	mVDSettings->sFps = toString(floor(mVDSettings->iFps));
	mMixes[0]->update();
	mVDAnimation->update();
	mVDRouter->update();

	updateWindowTitle();
}
void VideodrommLiveCodingApp::updateWindowTitle()
{
	//mMainWindow->setTitle(mVDSettings->sFps + " fps Live Coding");
}
void VideodrommLiveCodingApp::cleanup()
{
	if (!mIsShutDown)
	{
		mIsShutDown = true;
		CI_LOG_V("shutdown");
		ui::disconnectWindow(getWindow());
		ui::Shutdown();
		// save settings
		mVDSettings->save();
		mVDSession->save();
		deleteRenderWindows();
		mVDRouter->wsDisconnect();
		quit();
	}
}
void VideodrommLiveCodingApp::mouseDown(MouseEvent event)
{

}
void VideodrommLiveCodingApp::keyDown(KeyEvent event)
{

	if (!mVDAnimation->handleKeyDown(event)) {
		// Animation did not handle the key, so handle it here
		switch (event.getCode()) {
		case KeyEvent::KEY_ESCAPE:
			// quit the application
			quit();
			break;
		case KeyEvent::KEY_l:
			mVDAnimation->load();
			break;
		case KeyEvent::KEY_h:
			// mouse cursor
			mVDSettings->mCursorVisible = !mVDSettings->mCursorVisible;
			setUIVisibility(mVDSettings->mCursorVisible);
			break;
		}
	}
}

void VideodrommLiveCodingApp::keyUp(KeyEvent event)
{
	if (!mVDAnimation->handleKeyUp(event)) {
		// Animation did not handle the key, so handle it here
	}
}
void VideodrommLiveCodingApp::resizeWindow()
{
	mVDUI->resize();
}
void VideodrommLiveCodingApp::fileDrop(FileDropEvent event)
{
	int index = (int)(event.getX() / (mVDSettings->uiLargePreviewW + mVDSettings->uiMargin));
	ci::fs::path mPath = event.getFile(event.getNumFiles() - 1);
	string mFile = mPath.string();
	if (mMixes[0]->loadFileFromAbsolutePath(mFile, index) > -1) {
		// load success
		// reset zoom
		mVDAnimation->controlValues[22] = 1.0f;
	}
}

void VideodrommLiveCodingApp::drawRender()
{
	gl::clear(Color::black());
	//gl::setMatricesWindow(toPixels(getWindowSize()));
	gl::setMatricesWindow(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight, false);
	// live coding fbo gl::draw(mFbo->getColorTexture(), getWindowBounds());
	gl::draw(mMixes[0]->getMixTexture(), getWindowBounds());
}

void VideodrommLiveCodingApp::drawMain()
{
	mMainWindow->setTitle(mVDSettings->sFps + " fps Live Coding");

	gl::clear(Color::black());
	//	gl::setMatricesWindow(toPixels(getWindowSize()));
	gl::setMatricesWindow(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight, false);
	gl::draw(mMixes[0]->getMixTexture(), getWindowBounds());

	// imgui
	if (!mVDSettings->mCursorVisible) return;

	mVDUI->Run("UI", (int)getAverageFps());
	if (mVDUI->isReady()) {
	}

}

CINDER_APP(VideodrommLiveCodingApp, RendererGl, &VideodrommLiveCodingApp::prepare)

<commit_msg>shader and fbo preview drag n drop reuse fbo<commit_after>#include "VideodrommLiveCodingApp.h"

void VideodrommLiveCodingApp::prepare(Settings *settings)
{
	settings->setWindowSize(640, 480);
	//settings->setBorderless();
	settings->setWindowPos(0, 0);
}
void VideodrommLiveCodingApp::setup()
{
	// maximize fps
	disableFrameRate();
	gl::enableVerticalSync(false);
	// Settings
	mVDSettings = VDSettings::create();
	// Session
	mVDSession = VDSession::create(mVDSettings);
	// Utils
	mVDUtils = VDUtils::create(mVDSettings);
	// Animation
	mVDAnimation = VDAnimation::create(mVDSettings, mVDSession);
	// Message router
	mVDRouter = VDRouter::create(mVDSettings, mVDAnimation, mVDSession);
	// Mix
	mMixesFilepath = getAssetPath("") / mVDSettings->mAssetsPath / "mixes.xml";
	if (fs::exists(mMixesFilepath)) {
		// load textures from file if one exists
		mMixes = VDMix::readSettings(mVDSettings, mVDAnimation, mVDRouter, loadFile(mMixesFilepath));
	}
	else {
		// otherwise create a texture from scratch
		mMixes.push_back(VDMix::create(mVDSettings, mVDAnimation, mVDRouter));
	}
	mVDAnimation->tapTempo();

	mVDUtils->getWindowsResolution();
	setWindowSize(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight);

	mVDSettings->iResolution.x = mVDSettings->mRenderWidth;
	mVDSettings->iResolution.y = mVDSettings->mRenderHeight;
	// UI
	mVDUI = VDUI::create(mVDSettings, mMixes[0], mVDRouter, mVDAnimation, mVDSession);

	mouseGlobal = false;

	static float f = 0.0f;
	// mouse cursor and UI
	setUIVisibility(mVDSettings->mCursorVisible);
	// windows
	mIsShutDown = false;
	mIsResizing = true;
	mMainWindow = getWindow();
	mMainWindow->getSignalDraw().connect(std::bind(&VideodrommLiveCodingApp::drawMain, this));
	mMainWindow->getSignalResize().connect(std::bind(&VideodrommLiveCodingApp::resizeWindow, this));
	/*if (mVDSettings->mStandalone) {
		createRenderWindow();
		setWindowSize(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight);
		}
		else {

		}*/
}
void VideodrommLiveCodingApp::createRenderWindow()
{
	deleteRenderWindows();
	mVDUtils->getWindowsResolution();

	mVDSettings->iResolution.x = mVDSettings->mRenderWidth;
	mVDSettings->iResolution.y = mVDSettings->mRenderHeight;

	CI_LOG_V("createRenderWindow, resolution:" + toString(mVDSettings->iResolution.x) + "x" + toString(mVDSettings->iResolution.y));

	string windowName = "render";
	mRenderWindow = createWindow(Window::Format().size(mVDSettings->iResolution.x, mVDSettings->iResolution.y));

	// create instance of the window and store in vector
	allRenderWindows.push_back(mRenderWindow);

	mRenderWindow->setBorderless();
	mRenderWindow->getSignalDraw().connect(std::bind(&VideodrommLiveCodingApp::drawRender, this));
	mVDSettings->mRenderPosXY = ivec2(mVDSettings->mRenderX, mVDSettings->mRenderY);//20141214 was 0
	mRenderWindow->setPos(50, 50);
	mRenderWindowTimer = 0.0f;
	timeline().apply(&mRenderWindowTimer, 1.0f, 2.0f).finishFn([&]{ positionRenderWindow(); });
}
void VideodrommLiveCodingApp::positionRenderWindow()
{
	mRenderWindow->setPos(mVDSettings->mRenderX, mVDSettings->mRenderY);
}
void VideodrommLiveCodingApp::deleteRenderWindows()
{
#if defined( CINDER_MSW )
	for (auto wRef : allRenderWindows) DestroyWindow((HWND)mRenderWindow->getNative());
#endif
	allRenderWindows.clear();
}
void VideodrommLiveCodingApp::setUIVisibility(bool visible)
{
	if (visible)
	{
		showCursor();
	}
	else
	{
		hideCursor();
	}
}
void VideodrommLiveCodingApp::update()
{
	mVDSettings->iFps = getAverageFps();
	mVDSettings->sFps = toString(floor(mVDSettings->iFps));
	mMixes[0]->update();
	mVDAnimation->update();
	mVDRouter->update();

	updateWindowTitle();
}
void VideodrommLiveCodingApp::updateWindowTitle()
{
	//mMainWindow->setTitle(mVDSettings->sFps + " fps Live Coding");
}
void VideodrommLiveCodingApp::cleanup()
{
	if (!mIsShutDown)
	{
		mIsShutDown = true;
		CI_LOG_V("shutdown");
		ui::disconnectWindow(getWindow());
		ui::Shutdown();
		// save settings
		mVDSettings->save();
		mVDSession->save();
		deleteRenderWindows();
		mVDRouter->wsDisconnect();
		quit();
	}
}
void VideodrommLiveCodingApp::mouseDown(MouseEvent event)
{

}
void VideodrommLiveCodingApp::keyDown(KeyEvent event)
{

	if (!mVDAnimation->handleKeyDown(event)) {
		// Animation did not handle the key, so handle it here
		switch (event.getCode()) {
		case KeyEvent::KEY_ESCAPE:
			// quit the application
			quit();
			break;
		case KeyEvent::KEY_l:
			mVDAnimation->load();
			break;
		case KeyEvent::KEY_h:
			// mouse cursor
			mVDSettings->mCursorVisible = !mVDSettings->mCursorVisible;
			setUIVisibility(mVDSettings->mCursorVisible);
			break;
		}
	}
}

void VideodrommLiveCodingApp::keyUp(KeyEvent event)
{
	if (!mVDAnimation->handleKeyUp(event)) {
		// Animation did not handle the key, so handle it here
	}
}
void VideodrommLiveCodingApp::resizeWindow()
{
	mVDUI->resize();
}
void VideodrommLiveCodingApp::fileDrop(FileDropEvent event)
{
	int index = (int)(event.getX() / (mVDSettings->uiLargePreviewW + mVDSettings->uiMargin));
	int y = (int)(event.getY());
	if (index < 2 || y < mVDSettings->uiYPosRow3 || y > mVDSettings->uiYPosRow3 + mVDSettings->uiPreviewH) index = 0;
	ci::fs::path mPath = event.getFile(event.getNumFiles() - 1);
	string mFile = mPath.string();
	if (mMixes[0]->loadFileFromAbsolutePath(mFile, index) > -1) {
		// load success
		// reset zoom
		mVDAnimation->controlValues[22] = 1.0f;
	}
}

void VideodrommLiveCodingApp::drawRender()
{
	gl::clear(Color::black());
	//gl::setMatricesWindow(toPixels(getWindowSize()));
	gl::setMatricesWindow(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight, false);
	// live coding fbo gl::draw(mFbo->getColorTexture(), getWindowBounds());
	gl::draw(mMixes[0]->getMixTexture(), getWindowBounds());
}

void VideodrommLiveCodingApp::drawMain()
{
	mMainWindow->setTitle(mVDSettings->sFps + " fps Live Coding");

	gl::clear(Color::black());
	//	gl::setMatricesWindow(toPixels(getWindowSize()));
	gl::setMatricesWindow(mVDSettings->mRenderWidth, mVDSettings->mRenderHeight, false);
	gl::draw(mMixes[0]->getMixTexture(), getWindowBounds());

	// imgui
	if (!mVDSettings->mCursorVisible) return;

	mVDUI->Run("UI", (int)getAverageFps());
	if (mVDUI->isReady()) {
	}

}

CINDER_APP(VideodrommLiveCodingApp, RendererGl, &VideodrommLiveCodingApp::prepare)

<|endoftext|>


<commit_before>/* Copyright (c) 2008-2017 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "command.h"
#include "math/math.h"
#include "image.h"
#include "dwi/tractography/file.h"
#include "dwi/tractography/properties.h"
#include "dwi/tractography/resampling/arc.h"
#include "dwi/tractography/resampling/downsampler.h"
#include "dwi/tractography/resampling/endpoints.h"
#include "dwi/tractography/resampling/fixed_num_points.h"
#include "dwi/tractography/resampling/fixed_step_size.h"
#include "dwi/tractography/resampling/resampling.h"
#include "dwi/tractography/resampling/upsampler.h"

using namespace MR;
using namespace App;
using namespace DWI::Tractography;

void usage ()
{

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au) and J-Donald Tournier (jdtournier@gmail.com)";

  DESCRIPTION
  + "Resample each streamline to a new set of vertices. "
  + "This may be either increasing or decreasing the number of samples along "
    "each streamline, or changing the positions of the samples according to "
    "some specified trajectory.";

  ARGUMENTS
  + Argument ("in_tracks",  "the input track file").type_tracks_in()
  + Argument ("out_tracks", "the output resampled tracks").type_tracks_out();

  OPTIONS
    + Resampling::ResampleOption;

    // TODO Resample according to an exemplar streamline
}

typedef float value_type;

void run ()
{
  Properties properties;
  Reader<value_type> read (argument[0], properties);

  Resampling::Base* resampler = Resampling::get_resampler();

  float old_step_size = NaN;
  try {
    Properties::const_iterator i = properties.find ("output_step_size");
    if (i == properties.end()) {
      i = properties.find ("step_size");
      if (i != properties.end())
        old_step_size = to<float> (i->second);
    } else {
      old_step_size = to<float> (i->second);
    }
  } catch (...) {
    DEBUG ("Unable to read input track file step size");
  }

  if (std::isfinite (old_step_size)) {
    float new_step_size = NaN;
    if (typeid (*resampler) == typeid (Resampling::Downsampler))
      new_step_size = old_step_size * dynamic_cast<Resampling::Downsampler*> (resampler)->get_ratio();
    if (typeid (*resampler) == typeid (Resampling::FixedStepSize))
      new_step_size = dynamic_cast<Resampling::FixedStepSize*> (resampler)->get_step_size();
    if (typeid (*resampler) == typeid (Resampling::Upsampler))
      new_step_size = old_step_size / dynamic_cast<Resampling::Upsampler*> (resampler)->get_ratio();
    properties["output_step_size"] = std::isfinite (new_step_size) ? str(new_step_size) : "variable";
  }

  auto downsample = properties.find ("downsample_factor");
  if (downsample != properties.end())
    properties.erase (downsample);

  DWI::Tractography::Writer<value_type> writer (argument[1], properties);

  size_t skipped = 0, count = 0;
  auto progress_message = [&](){ return "sampling streamlines (count: " + str(count) + ", skipped: " + str(skipped) + ")"; };
  ProgressBar progress ("sampling streamlines");

  // Single-threaded in order to retain order of streamlines in the output file
  DWI::Tractography::Streamline<value_type> tck;
  while (read (tck)) {
    if (!resampler->limits (tck)) { skipped++; continue; }
    (*resampler) (tck);
    writer (tck);
    ++count;
    progress.update (progress_message);
  }
  progress.set_text (progress_message());

}

<commit_msg>tckresample: Write "output_step_size" field with -step_size option<commit_after>/* Copyright (c) 2008-2017 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "command.h"
#include "math/math.h"
#include "image.h"
#include "dwi/tractography/file.h"
#include "dwi/tractography/properties.h"
#include "dwi/tractography/resampling/arc.h"
#include "dwi/tractography/resampling/downsampler.h"
#include "dwi/tractography/resampling/endpoints.h"
#include "dwi/tractography/resampling/fixed_num_points.h"
#include "dwi/tractography/resampling/fixed_step_size.h"
#include "dwi/tractography/resampling/resampling.h"
#include "dwi/tractography/resampling/upsampler.h"

using namespace MR;
using namespace App;
using namespace DWI::Tractography;

void usage ()
{

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au) and J-Donald Tournier (jdtournier@gmail.com)";

  DESCRIPTION
  + "Resample each streamline to a new set of vertices. "
  + "This may be either increasing or decreasing the number of samples along "
    "each streamline, or changing the positions of the samples according to "
    "some specified trajectory.";

  ARGUMENTS
  + Argument ("in_tracks",  "the input track file").type_tracks_in()
  + Argument ("out_tracks", "the output resampled tracks").type_tracks_out();

  OPTIONS
    + Resampling::ResampleOption;

    // TODO Resample according to an exemplar streamline
}

typedef float value_type;

void run ()
{
  Properties properties;
  Reader<value_type> read (argument[0], properties);

  Resampling::Base* resampler = Resampling::get_resampler();

  float old_step_size = NaN;
  try {
    Properties::const_iterator i = properties.find ("output_step_size");
    if (i == properties.end()) {
      i = properties.find ("step_size");
      if (i != properties.end())
        old_step_size = to<float> (i->second);
    } else {
      old_step_size = to<float> (i->second);
    }
  } catch (...) {
    DEBUG ("Unable to read input track file step size");
  }

  float new_step_size = NaN;
  if (typeid (*resampler) == typeid (Resampling::FixedStepSize)) {
    new_step_size = dynamic_cast<Resampling::FixedStepSize*> (resampler)->get_step_size();
  } else if (std::isfinite (old_step_size)) {
    if (typeid (*resampler) == typeid (Resampling::Downsampler))
      new_step_size = old_step_size * dynamic_cast<Resampling::Downsampler*> (resampler)->get_ratio();
    if (typeid (*resampler) == typeid (Resampling::Upsampler))
      new_step_size = old_step_size / dynamic_cast<Resampling::Upsampler*> (resampler)->get_ratio();
  }
  properties["output_step_size"] = std::isfinite (new_step_size) ? str(new_step_size) : "variable";

  auto downsample = properties.find ("downsample_factor");
  if (downsample != properties.end())
    properties.erase (downsample);

  DWI::Tractography::Writer<value_type> writer (argument[1], properties);

  size_t skipped = 0, count = 0;
  auto progress_message = [&](){ return "sampling streamlines (count: " + str(count) + ", skipped: " + str(skipped) + ")"; };
  ProgressBar progress ("sampling streamlines");

  // Single-threaded in order to retain order of streamlines in the output file
  DWI::Tractography::Streamline<value_type> tck;
  while (read (tck)) {
    if (!resampler->limits (tck)) { skipped++; continue; }
    (*resampler) (tck);
    writer (tck);
    ++count;
    progress.update (progress_message);
  }
  progress.set_text (progress_message());

}

<|endoftext|>


<commit_before>#include "ReverseLinkedList.hpp"

ListNode *ReverseLinkedList::reverseList(ListNode *head) {
    if (head == nullptr)
        return head;

    ListNode *prev = nullptr;
    ListNode *now = head;
    ListNode *next = now->next;

    while (next != nullptr) {
        now->next = prev;
        prev = now;
        now = next;
        next = now->next;
    }

    now->next = prev;
    return now;
}
<commit_msg>Refine Problem 206. Reverse Linked List<commit_after>#include "ReverseLinkedList.hpp"

ListNode *ReverseLinkedList::reverseList(ListNode *head) {
    ListNode *tail = head;
    while (tail && tail->next)
        tail = tail->next;

    if (head == tail) return head;

    ListNode *a = head;
    ListNode *b = a->next;
    while (a != tail) {
        ListNode *t = b->next;
        b->next = a;
        a = b;
        b = t;
    }
    head->next = nullptr;

    return tail;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <vector>
#include <endian.h>

#define LOGLEVEL VERBOSE

#include "utils/logging.h"
//#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/NMRAnetEventRegistry.hxx"
//#include "if/nmranet_if.h"
#include "core/nmranet_event.h"
#include "nmranet/EventHandlerTemplates.hxx"

// Abstract class for representing iteration through a container for event
// handlers.
class EventIterator : public ProxyNotifiable {
 public:
  //! Creates an EventIterator.
  //
  //! @param parent is a Notifiable. Any notifications coming into the
  //! Notifiables created by NewCallback will be forwarded to this callback.
  EventIterator()
      : event_(nullptr), done_(nullptr) {}

  //! Steps the iteration.
  //
  //! @returns the next entry or NULL if the iteration is done.
  //
  //! May be called many times after the iteratin is ended and should
  //! consistently return NULL.
  virtual NMRAnetEventHandler* NextEntry() = 0;

  //! Sets up variables used during iteration.
  //
  //! @param event is the EventReport that will be used for this iteration.
  //
  //! @param done is the Notifiable that shall be called when the iteration is
  //! completed.
  void InitIterator(EventReport* event, ::Notifiable* done) {
    HASSERT(event_ == nullptr);
    HASSERT(done_ == nullptr);
    event_ = event;
    done_ = done;
  }

  //! Resets iteration variables.
  void ClearIteration() {
    event_ = nullptr;
    done_ = nullptr;
  }

  //! @returns the EventReport structure used for this iteration.
  EventReport* event() { return event_; }

  //! @returns the callback to be called when the iteration is completed.
  ::Notifiable* done() { return done_; }

 private:
  // Stores iteration arguments.
  EventReport* event_;
  // Stores the iteration completion callback.
  ::Notifiable* done_;
  // Proxies incoming notifications to this parent.
  ::Notifiable* parent_;
  // When there is an incoming notification, this is set to true.
  bool was_notified_;
};

//! An implementation of the EventIterator abstract class that iterates through
//! an STL container's range by the begin-end iterators.
template <class IT>
class StlIterator : public EventIterator {
 public:
  StlIterator() {}

  //! Initializes the iteration with begin-end iterator pair.
  void Set(IT begin, IT end) {
    it_ = begin;
    end_ = end;
  }

  //! Returns the next iterated entry.
  virtual NMRAnetEventHandler* NextEntry() {
    if (it_ == end_)
      return NULL;
    else
      return *it_++;
  }

 private:
  //! The current iterator.
  IT it_;
  //! The end of the iteration.
  IT end_;
};

/**
 *  This control flow performs two iterations over event handlers in
 *  parallel. There isa high-priority iteration for regular incoming event
 *  calls, and there is a low-priority iteration for global identify
 *  calls. While there is any high-priority iteration, the low-priority
 *  iteration is stopped.
 *
 *  LOCKING:
 *
 *  At any point in time there can be only one EventHandler child called. This
 *  is enforced by locking the event_handler_mutex when a child is
 *  called. All our incoming calls are also with this lock held.
 *
 *  The high-priority iteration progresses without ever releasing the lock.
 *
 *  The low-priority iteration releases the mutex after every entry, and then
 *  immediately tries to reacquire it (thereby yielding to the back of the
 *  mutex's queue). This means that between any two children being called on
 *  the low-pri iteration and entire high-pri iteration will complete.
 *
 */
class DualIteratorFlow : public ControlFlow, public ProxyEventHandler {
 public:
  DualIteratorFlow(Executor* executor,
                   EventIterator* standard_iterator,
                   EventIterator* global_iterator)
      : ControlFlow(executor, NULL),
        standard_iterator_(standard_iterator),
        global_iterator_(global_iterator) {
    StartFlowAt(ST(StateInIteration));
  }

  //! Implementations have to override this to re-set the standard_iterator
  //! from the information in standard_iterator->event().
  virtual void InitStandardIterator() = 0;

  //! Handler function for high-priority event calls. Starts a
  //! StandardIterator.
  //
  //! This function is called (by the ProxyEventHandler) for any event handler
  //! functions we didn't override explicitly, that is, everything except
  //! Identify Global.
  virtual void HandlerFn(EventHandlerFunction fn,
                         EventReport* event,
                         Notifiable* done) {
    LOG(VERBOSE, "Dual::Handler, event %016llx", event->event);
    event_handler_mutex.AssertLocked();
    proxy_fn_ = fn;
    standard_iterator_->InitIterator(event, done);
    InitStandardIterator();
    this->Notify();
  }

  //! Implementations have to override this to re-set the global_iterator
  //! based on the information in global_iterator->event().
  virtual void InitGlobalIterator() = 0;

  virtual void HandleIdentifyGlobal(EventReport* event, Notifiable* done) {
    LOG(VERBOSE, "Dual::IdentifyGlobal");
    event_handler_mutex.AssertLocked();
    // We immediately release the global iterator mutex and will acquire it
    // inside when we try to call children.
    event_handler_mutex.Unlock();
    global_iterator_->InitIterator(event, done);
    InitGlobalIterator();
    this->Notify();
  }

 protected:
  ControlFlowAction StateInIteration() {
    // We first try a standard iteration.
    if (standard_iterator_->done())
      return CallImmediately(ST(TryStandardIteration));
    // Then a global iteration.
    if (global_iterator_->done())
      return CallImmediately(ST(GetGlobalIterationLock));
    // Give up and wait for incoming messages.
    return WaitForNotification();
  }

  ControlFlowAction TryStandardIteration() {
    NMRAnetEventHandler* handler = standard_iterator_->NextEntry();
    if (!handler) {
      // Iteration done.
      LOG(VERBOSE, "Standard iteration done");
      Notifiable* d = standard_iterator_->done();
      HASSERT(d);
      standard_iterator_->ClearIteration();
      d->Notify();
      return YieldAndCall(ST(StateInIteration));
    }
    (handler->*proxy_fn_)(standard_iterator_->event(),
                          standard_iterator_->NewCallback(this));
    return CallImmediately(ST(WaitForStandardReturn));
  }

  ControlFlowAction WaitForStandardReturn() {
    LOG(VERBOSE, "Standard entry return");
    if (!standard_iterator_->HasBeenNotified())
      return WaitForNotification();
    return CallImmediately(ST(TryStandardIteration));
  }

  ControlFlowAction GetGlobalIterationLock() {
    return Allocate(&event_handler_mutex, ST(CallGlobalIteration));
  }

  ControlFlowAction CallGlobalIteration() {
    NMRAnetEventHandler* handler = global_iterator_->NextEntry();
    if (!handler) {
      // Iteration done. We hand back the iterator lock.
      Notifiable* d = global_iterator_->done();
      HASSERT(d);
      global_iterator_->ClearIteration();
      d->Notify();
      global_iterator_->done()->Notify();
      return YieldAndCall(ST(StateInIteration));
    }
    handler->HandleIdentifyGlobal(global_iterator_->event(),
                                  global_iterator_->NewCallback(this));
    return CallImmediately(ST(WaitForGlobalReturn));
  }

  ControlFlowAction WaitForGlobalReturn() {
    if (!global_iterator_->HasBeenNotified())
      return WaitForNotification();
    // Releases the iteration lock and yields to other control flows that might
    // want it.
    event_handler_mutex.Unlock();
    return YieldAndCall(ST(StateInIteration));
  }

 private:
  //! Holds which event handler function the standard iteration should call.
  EventHandlerFunction proxy_fn_;
  EventIterator* standard_iterator_;
  EventIterator* global_iterator_;
};

class VectorEventHandlers : public DualIteratorFlow, public NMRAnetEventRegistry {
 public:
  VectorEventHandlers(Executor* executor)
      : DualIteratorFlow(executor,
                         &standard_iterator_impl_,
                         &global_iterator_impl_) {}

  virtual void InitStandardIterator() {
    standard_iterator_impl_.Set(handlers_.begin(), handlers_.end());
  }

  virtual void InitGlobalIterator() {
    global_iterator_impl_.Set(handlers_.begin(), handlers_.end());
  }

  virtual void RegisterHandler(NMRAnetEventHandler* handler, EventId event, unsigned mask) {
    // @TODO(balazs.racz): need some kind of locking here.
    handlers_.push_back(handler);
  }
  virtual void UnregisterHandler(NMRAnetEventHandler* handler, EventId event, unsigned mask) {
    // @TODO(balazs.racz): need some kind of locking here.
    handlers_.erase(std::remove(handlers_.begin(), handlers_.end(), handler));
  }

  virtual NMRAnetEventHandler* EventHandler() {
    return this;
  }

 private:
  typedef std::vector<NMRAnetEventHandler*> HandlersList;
  HandlersList handlers_;
  StlIterator<HandlersList::iterator> standard_iterator_impl_;
  StlIterator<HandlersList::iterator> global_iterator_impl_;
};
<commit_msg>Makes StlIterator also work with stl pair-second containers.<commit_after>#include <algorithm>
#include <vector>
#include <endian.h>

#define LOGLEVEL VERBOSE

#include "executor/control_flow.hxx"
#include "utils/logging.h"
//#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/NMRAnetEventRegistry.hxx"
//#include "if/nmranet_if.h"
#include "core/nmranet_event.h"
#include "nmranet/EventHandlerTemplates.hxx"

// Abstract class for representing iteration through a container for event
// handlers.
class EventIterator : public ProxyNotifiable {
 public:
  //! Creates an EventIterator.
  //
  //! @param parent is a Notifiable. Any notifications coming into the
  //! Notifiables created by NewCallback will be forwarded to this callback.
  EventIterator()
      : event_(nullptr), done_(nullptr) {}

  //! Steps the iteration.
  //
  //! @returns the next entry or NULL if the iteration is done.
  //
  //! May be called many times after the iteratin is ended and should
  //! consistently return NULL.
  virtual NMRAnetEventHandler* NextEntry() = 0;

  //! Sets up variables used during iteration.
  //
  //! @param event is the EventReport that will be used for this iteration.
  //
  //! @param done is the Notifiable that shall be called when the iteration is
  //! completed.
  void InitIterator(EventReport* event, ::Notifiable* done) {
    HASSERT(event_ == nullptr);
    HASSERT(done_ == nullptr);
    event_ = event;
    done_ = done;
  }

  //! Resets iteration variables.
  void ClearIteration() {
    event_ = nullptr;
    done_ = nullptr;
  }

  //! @returns the EventReport structure used for this iteration.
  EventReport* event() { return event_; }

  //! @returns the callback to be called when the iteration is completed.
  ::Notifiable* done() { return done_; }

 private:
  // Stores iteration arguments.
  EventReport* event_;
  // Stores the iteration completion callback.
  ::Notifiable* done_;
  // Proxies incoming notifications to this parent.
  ::Notifiable* parent_;
  // When there is an incoming notification, this is set to true.
  bool was_notified_;
};

//! An implementation of the EventIterator abstract class that iterates through
//! an STL container's range by the begin-end iterators.
template <class IT>
class StlIterator : public EventIterator {
 public:
  StlIterator() {}

  //! Initializes the iteration with begin-end iterator pair.
  void Set(IT begin, IT end) {
    it_ = begin;
    end_ = end;
  }

 protected:
  //! The current iterator.
  IT it_;
  //! The end of the iteration.
  IT end_;
};

template<class IT>
class StraightStlIterator : public StlIterator<IT> {
 public:
  //! Returns the next iterated entry.
  virtual NMRAnetEventHandler* NextEntry() {
    if (this->it_ == this->end_)
      return NULL;
    else
      return *(this->it_)++;
  }
};

/**
 *  This control flow performs two iterations over event handlers in
 *  parallel. There isa high-priority iteration for regular incoming event
 *  calls, and there is a low-priority iteration for global identify
 *  calls. While there is any high-priority iteration, the low-priority
 *  iteration is stopped.
 *
 *  LOCKING:
 *
 *  At any point in time there can be only one EventHandler child called. This
 *  is enforced by locking the event_handler_mutex when a child is
 *  called. All our incoming calls are also with this lock held.
 *
 *  The high-priority iteration progresses without ever releasing the lock.
 *
 *  The low-priority iteration releases the mutex after every entry, and then
 *  immediately tries to reacquire it (thereby yielding to the back of the
 *  mutex's queue). This means that between any two children being called on
 *  the low-pri iteration and entire high-pri iteration will complete.
 *
 */
class DualIteratorFlow : public ControlFlow, public ProxyEventHandler {
 public:
  DualIteratorFlow(Executor* executor,
                   EventIterator* standard_iterator,
                   EventIterator* global_iterator)
      : ControlFlow(executor, NULL),
        standard_iterator_(standard_iterator),
        global_iterator_(global_iterator) {
    StartFlowAt(ST(StateInIteration));
  }

  //! Implementations have to override this to re-set the standard_iterator
  //! from the information in standard_iterator->event().
  virtual void InitStandardIterator() = 0;

  //! Handler function for high-priority event calls. Starts a
  //! StandardIterator.
  //
  //! This function is called (by the ProxyEventHandler) for any event handler
  //! functions we didn't override explicitly, that is, everything except
  //! Identify Global.
  virtual void HandlerFn(EventHandlerFunction fn,
                         EventReport* event,
                         Notifiable* done) {
    LOG(VERBOSE, "Dual::Handler, event %016llx", event->event);
    event_handler_mutex.AssertLocked();
    proxy_fn_ = fn;
    standard_iterator_->InitIterator(event, done);
    InitStandardIterator();
    this->Notify();
  }

  //! Implementations have to override this to re-set the global_iterator
  //! based on the information in global_iterator->event().
  virtual void InitGlobalIterator() = 0;

  virtual void HandleIdentifyGlobal(EventReport* event, Notifiable* done) {
    LOG(VERBOSE, "Dual::IdentifyGlobal");
    event_handler_mutex.AssertLocked();
    // We immediately release the global iterator mutex and will acquire it
    // inside when we try to call children.
    event_handler_mutex.Unlock();
    global_iterator_->InitIterator(event, done);
    InitGlobalIterator();
    this->Notify();
  }

 protected:
  ControlFlowAction StateInIteration() {
    // We first try a standard iteration.
    if (standard_iterator_->done())
      return CallImmediately(ST(TryStandardIteration));
    // Then a global iteration.
    if (global_iterator_->done())
      return CallImmediately(ST(GetGlobalIterationLock));
    // Give up and wait for incoming messages.
    return WaitForNotification();
  }

  ControlFlowAction TryStandardIteration() {
    NMRAnetEventHandler* handler = standard_iterator_->NextEntry();
    if (!handler) {
      // Iteration done.
      LOG(VERBOSE, "Standard iteration done");
      Notifiable* d = standard_iterator_->done();
      HASSERT(d);
      standard_iterator_->ClearIteration();
      d->Notify();
      return YieldAndCall(ST(StateInIteration));
    }
    (handler->*proxy_fn_)(standard_iterator_->event(),
                          standard_iterator_->NewCallback(this));
    return CallImmediately(ST(WaitForStandardReturn));
  }

  ControlFlowAction WaitForStandardReturn() {
    LOG(VERBOSE, "Standard entry return");
    if (!standard_iterator_->HasBeenNotified())
      return WaitForNotification();
    return CallImmediately(ST(TryStandardIteration));
  }

  ControlFlowAction GetGlobalIterationLock() {
    return Allocate(&event_handler_mutex, ST(CallGlobalIteration));
  }

  ControlFlowAction CallGlobalIteration() {
    NMRAnetEventHandler* handler = global_iterator_->NextEntry();
    if (!handler) {
      // Iteration done. We hand back the iterator lock.
      Notifiable* d = global_iterator_->done();
      HASSERT(d);
      global_iterator_->ClearIteration();
      d->Notify();
      global_iterator_->done()->Notify();
      return YieldAndCall(ST(StateInIteration));
    }
    handler->HandleIdentifyGlobal(global_iterator_->event(),
                                  global_iterator_->NewCallback(this));
    return CallImmediately(ST(WaitForGlobalReturn));
  }

  ControlFlowAction WaitForGlobalReturn() {
    if (!global_iterator_->HasBeenNotified())
      return WaitForNotification();
    // Releases the iteration lock and yields to other control flows that might
    // want it.
    event_handler_mutex.Unlock();
    return YieldAndCall(ST(StateInIteration));
  }

 private:
  //! Holds which event handler function the standard iteration should call.
  EventHandlerFunction proxy_fn_;
  EventIterator* standard_iterator_;
  EventIterator* global_iterator_;
};

class VectorEventHandlers : public DualIteratorFlow, public NMRAnetEventRegistry {
 public:
  VectorEventHandlers(Executor* executor)
      : DualIteratorFlow(executor,
                         &standard_iterator_impl_,
                         &global_iterator_impl_) {}

  virtual void InitStandardIterator() {
    standard_iterator_impl_.Set(handlers_.begin(), handlers_.end());
  }

  virtual void InitGlobalIterator() {
    global_iterator_impl_.Set(handlers_.begin(), handlers_.end());
  }

  virtual void RegisterHandler(NMRAnetEventHandler* handler, EventId event, unsigned mask) {
    // @TODO(balazs.racz): need some kind of locking here.
    handlers_.push_back(handler);
  }
  virtual void UnregisterHandler(NMRAnetEventHandler* handler, EventId event, unsigned mask) {
    // @TODO(balazs.racz): need some kind of locking here.
    handlers_.erase(std::remove(handlers_.begin(), handlers_.end(), handler));
  }

  virtual NMRAnetEventHandler* EventHandler() {
    return this;
  }

 private:
  typedef std::vector<NMRAnetEventHandler*> HandlersList;
  HandlersList handlers_;
  StraightStlIterator<HandlersList::iterator> standard_iterator_impl_;
  StraightStlIterator<HandlersList::iterator> global_iterator_impl_;
};
<|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-2006 Torus Knot Software Ltd
Copyright (c) 2006 Matthias Fink, netAllied GmbH <matthias.fink@web.de>
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePolygon.h"
#include "OgreException.h"
#include "OgreVector3.h"

namespace Ogre
{

	//-----------------------------------------------------------------------
	Polygon::Polygon()
	: mNormal( Vector3::ZERO )
	, mIsNormalSet(false)
	{
		// reserve space for 6 vertices to reduce allocation cost
		mVertexList.reserve(6);
	}
	//-----------------------------------------------------------------------
	Polygon::~Polygon()
	{
	}
	//-----------------------------------------------------------------------
	Polygon::Polygon( const Polygon& cpy )
	{
		mVertexList = cpy.mVertexList;
		mNormal = cpy.mNormal;
		mIsNormalSet = cpy.mIsNormalSet;
	}
	//-----------------------------------------------------------------------
	void Polygon::insertVertex(const Vector3& vdata, size_t vertex )
	{
		// TODO: optional: check planarity
		OgreAssert(vertex <= getVertexCount(), "Insert position out of range" );

		VertexList::iterator it = mVertexList.begin();

		std::advance(it, vertex);
		mVertexList.insert(it, vdata);

	}
	//-----------------------------------------------------------------------
	void Polygon::insertVertex(const Vector3& vdata)
	{
		mVertexList.push_back(vdata);
	}
	//-----------------------------------------------------------------------
	const Vector3& Polygon::getVertex( size_t vertex ) const
	{
		OgreAssert(vertex < getVertexCount(), "Search position out of range");

		return mVertexList[vertex];
	}
	//-----------------------------------------------------------------------
	void Polygon::setVertex(const Vector3& vdata, size_t vertex )
	{
		// TODO: optional: check planarity
		OgreAssert(vertex < getVertexCount(), "Search position out of range" );

		// set new vertex
		mVertexList[ vertex ] = vdata;
	}
	//-----------------------------------------------------------------------
	void Polygon::removeDuplicates( void )
	{
		for ( size_t i = 0; i < getVertexCount(); ++i )
		{
			const Vector3& a = getVertex( i );
			const Vector3& b = getVertex( (i + 1)%getVertexCount() );

			if (a.positionEquals(b))
			{
				deleteVertex(i);
				--i;
			}
		}
	}
	//-----------------------------------------------------------------------
	size_t Polygon::getVertexCount( void ) const
	{
		return mVertexList.size();
	}
	//-----------------------------------------------------------------------
	const Vector3& Polygon::getNormal( void ) const
	{
		OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" );

		updateNormal();

		return mNormal;
	}
	//-----------------------------------------------------------------------
	void Polygon::updateNormal( void ) const
	{
		OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" );

		if (mIsNormalSet)
			return;

		// vertex order is ccw
		const Vector3& a = getVertex( 0 );
		const Vector3& b = getVertex( 1 );
		const Vector3& c = getVertex( 2 );

		// used method: Newell
		mNormal.x = 0.5f * ( (a.y - b.y) * (a.z + b.z) +
							   (b.y - c.y) * (b.z + c.z) +
							   (c.y - a.y) * (c.z + a.z));

		mNormal.y = 0.5f * ( (a.z - b.z) * (a.x + b.x) +
							   (b.z - c.z) * (b.x + c.x) +
							   (c.z - a.z) * (c.x + a.x));

		mNormal.z = 0.5f * ( (a.x - b.x) * (a.y + b.y) +
							   (b.x - c.x) * (b.y + c.y) +
							   (c.x - a.x) * (c.y + a.y));

		mNormal.normalise();

		mIsNormalSet = true;

	}
	//-----------------------------------------------------------------------
	void Polygon::deleteVertex( size_t vertex )
	{
		OgreAssert( vertex < getVertexCount(), "Search position out of range" );

		VertexList::iterator it = mVertexList.begin();
		std::advance(it, vertex);

		mVertexList.erase( it );
	}
	//-----------------------------------------------------------------------
	void Polygon::storeEdges( Polygon::EdgeMap *edgeMap ) const
	{
		OgreAssert( edgeMap != NULL, "EdgeMap ptr is NULL" );

		size_t vertexCount = getVertexCount();

		for ( size_t i = 0; i < vertexCount; ++i )
		{
			edgeMap->insert( Edge( getVertex( i ), getVertex( ( i + 1 ) % vertexCount ) ) );
		}
	}
	//-----------------------------------------------------------------------
	void Polygon::reset( void )
	{
		// could use swap() to free memory here, but assume most may be reused so avoid realloc
		mVertexList.clear();

		mIsNormalSet = false;
	}
	//-----------------------------------------------------------------------
	bool Polygon::operator == (const Polygon& rhs) const
	{
		if ( getVertexCount() != rhs.getVertexCount() )
			return false;

		// Compare vertices. They may differ in its starting position.
		// find start
		size_t start;
		bool foundStart = false;
		for (size_t i = 0; i < getVertexCount(); ++i )
		{
			if (getVertex(0).positionEquals(rhs.getVertex(i)))
			{
				start = i;
				foundStart = true;
				break;
			}
		}

		if (!foundStart)
			return false;

		for (size_t i = 0; i < getVertexCount(); ++i )
		{
			const Vector3& vA = getVertex( i );
			const Vector3& vB = rhs.getVertex( ( i + start) % getVertexCount() );

			if (!vA.positionEquals(vB))
				return false;
		}

		return true;
	}
	//-----------------------------------------------------------------------
	std::ostream& operator<< ( std::ostream& strm, const Polygon& poly )
	{
		strm << "NUM VERTICES: " << poly.getVertexCount() << std::endl;

		for (size_t j = 0; j < poly.getVertexCount(); ++j )
		{
			strm << "VERTEX " << j << ": " << poly.getVertex( j ) << std::endl;
		}

		return strm;
	}
	//-----------------------------------------------------------------------
	bool Polygon::isPointInside(const Vector3& point) const
	{
		// sum the angles
		Real anglesum = 0;
		size_t n = getVertexCount();
		for (size_t i = 0; i < n; i++)
		{
			const Vector3& p1 = getVertex(i);
			const Vector3& p2 = getVertex((i + 1) % n);

			Vector3 v1 = p1 - point;
			Vector3 v2 = p2 - point;

			Real len1 = v1.length();
			Real len2 = v2.length();

			if (Math::RealEqual(len1 * len2, 0.0f, 1e-6f))
			{
				// We are on a vertex so consider this inside
				return true;
			}
			else
			{
				Real costheta = v1.dotProduct(v2) / (len1 * len2);
				anglesum += acos(costheta);
			}
		}

		// result should be 2*PI if point is inside poly
		return Math::RealEqual(anglesum, Math::TWO_PI, 1e-6f);

	}
}
<commit_msg>Make the comparisons a little fuzzier<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-2006 Torus Knot Software Ltd
Copyright (c) 2006 Matthias Fink, netAllied GmbH <matthias.fink@web.de>
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePolygon.h"
#include "OgreException.h"
#include "OgreVector3.h"

namespace Ogre
{

	//-----------------------------------------------------------------------
	Polygon::Polygon()
	: mNormal( Vector3::ZERO )
	, mIsNormalSet(false)
	{
		// reserve space for 6 vertices to reduce allocation cost
		mVertexList.reserve(6);
	}
	//-----------------------------------------------------------------------
	Polygon::~Polygon()
	{
	}
	//-----------------------------------------------------------------------
	Polygon::Polygon( const Polygon& cpy )
	{
		mVertexList = cpy.mVertexList;
		mNormal = cpy.mNormal;
		mIsNormalSet = cpy.mIsNormalSet;
	}
	//-----------------------------------------------------------------------
	void Polygon::insertVertex(const Vector3& vdata, size_t vertex )
	{
		// TODO: optional: check planarity
		OgreAssert(vertex <= getVertexCount(), "Insert position out of range" );

		VertexList::iterator it = mVertexList.begin();

		std::advance(it, vertex);
		mVertexList.insert(it, vdata);

	}
	//-----------------------------------------------------------------------
	void Polygon::insertVertex(const Vector3& vdata)
	{
		mVertexList.push_back(vdata);
	}
	//-----------------------------------------------------------------------
	const Vector3& Polygon::getVertex( size_t vertex ) const
	{
		OgreAssert(vertex < getVertexCount(), "Search position out of range");

		return mVertexList[vertex];
	}
	//-----------------------------------------------------------------------
	void Polygon::setVertex(const Vector3& vdata, size_t vertex )
	{
		// TODO: optional: check planarity
		OgreAssert(vertex < getVertexCount(), "Search position out of range" );

		// set new vertex
		mVertexList[ vertex ] = vdata;
	}
	//-----------------------------------------------------------------------
	void Polygon::removeDuplicates( void )
	{
		for ( size_t i = 0; i < getVertexCount(); ++i )
		{
			const Vector3& a = getVertex( i );
			const Vector3& b = getVertex( (i + 1)%getVertexCount() );

			if (a.positionEquals(b))
			{
				deleteVertex(i);
				--i;
			}
		}
	}
	//-----------------------------------------------------------------------
	size_t Polygon::getVertexCount( void ) const
	{
		return mVertexList.size();
	}
	//-----------------------------------------------------------------------
	const Vector3& Polygon::getNormal( void ) const
	{
		OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" );

		updateNormal();

		return mNormal;
	}
	//-----------------------------------------------------------------------
	void Polygon::updateNormal( void ) const
	{
		OgreAssert( getVertexCount() >= 3, "Insufficient vertex count!" );

		if (mIsNormalSet)
			return;

		// vertex order is ccw
		const Vector3& a = getVertex( 0 );
		const Vector3& b = getVertex( 1 );
		const Vector3& c = getVertex( 2 );

		// used method: Newell
		mNormal.x = 0.5f * ( (a.y - b.y) * (a.z + b.z) +
							   (b.y - c.y) * (b.z + c.z) +
							   (c.y - a.y) * (c.z + a.z));

		mNormal.y = 0.5f * ( (a.z - b.z) * (a.x + b.x) +
							   (b.z - c.z) * (b.x + c.x) +
							   (c.z - a.z) * (c.x + a.x));

		mNormal.z = 0.5f * ( (a.x - b.x) * (a.y + b.y) +
							   (b.x - c.x) * (b.y + c.y) +
							   (c.x - a.x) * (c.y + a.y));

		mNormal.normalise();

		mIsNormalSet = true;

	}
	//-----------------------------------------------------------------------
	void Polygon::deleteVertex( size_t vertex )
	{
		OgreAssert( vertex < getVertexCount(), "Search position out of range" );

		VertexList::iterator it = mVertexList.begin();
		std::advance(it, vertex);

		mVertexList.erase( it );
	}
	//-----------------------------------------------------------------------
	void Polygon::storeEdges( Polygon::EdgeMap *edgeMap ) const
	{
		OgreAssert( edgeMap != NULL, "EdgeMap ptr is NULL" );

		size_t vertexCount = getVertexCount();

		for ( size_t i = 0; i < vertexCount; ++i )
		{
			edgeMap->insert( Edge( getVertex( i ), getVertex( ( i + 1 ) % vertexCount ) ) );
		}
	}
	//-----------------------------------------------------------------------
	void Polygon::reset( void )
	{
		// could use swap() to free memory here, but assume most may be reused so avoid realloc
		mVertexList.clear();

		mIsNormalSet = false;
	}
	//-----------------------------------------------------------------------
	bool Polygon::operator == (const Polygon& rhs) const
	{
		if ( getVertexCount() != rhs.getVertexCount() )
			return false;

		// Compare vertices. They may differ in its starting position.
		// find start
		size_t start;
		bool foundStart = false;
		for (size_t i = 0; i < getVertexCount(); ++i )
		{
			if (getVertex(0).positionEquals(rhs.getVertex(i)))
			{
				start = i;
				foundStart = true;
				break;
			}
		}

		if (!foundStart)
			return false;

		for (size_t i = 0; i < getVertexCount(); ++i )
		{
			const Vector3& vA = getVertex( i );
			const Vector3& vB = rhs.getVertex( ( i + start) % getVertexCount() );

			if (!vA.positionEquals(vB))
				return false;
		}

		return true;
	}
	//-----------------------------------------------------------------------
	std::ostream& operator<< ( std::ostream& strm, const Polygon& poly )
	{
		strm << "NUM VERTICES: " << poly.getVertexCount() << std::endl;

		for (size_t j = 0; j < poly.getVertexCount(); ++j )
		{
			strm << "VERTEX " << j << ": " << poly.getVertex( j ) << std::endl;
		}

		return strm;
	}
	//-----------------------------------------------------------------------
	bool Polygon::isPointInside(const Vector3& point) const
	{
		// sum the angles
		Real anglesum = 0;
		size_t n = getVertexCount();
		for (size_t i = 0; i < n; i++)
		{
			const Vector3& p1 = getVertex(i);
			const Vector3& p2 = getVertex((i + 1) % n);

			Vector3 v1 = p1 - point;
			Vector3 v2 = p2 - point;

			Real len1 = v1.length();
			Real len2 = v2.length();

			if (Math::RealEqual(len1 * len2, 0.0f, 1e-4f))
			{
				// We are on a vertex so consider this inside
				return true;
			}
			else
			{
				Real costheta = v1.dotProduct(v2) / (len1 * len2);
				anglesum += acos(costheta);
			}
		}

		// result should be 2*PI if point is inside poly
		return Math::RealEqual(anglesum, Math::TWO_PI, 1e-4f);

	}
}
<|endoftext|>