<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QImage>
#include <QtDebug>
#include <QDir>
#include <QMessageBox>
#include <qmath.h>
#include <math.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString versionString;
    versionString.append(APP_VERSION);
    qDebug() << versionString;
    ui->labVersion->setText("Version: " + versionString);
    cursor = new QCursor();
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updatePos()));

    scene = new QGraphicsScene(ui->graphicsView);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    calc = new QPixelCalculator(this);

    patientInfoString = "PatientInfo";
    testInfoString = "TestInfo";
    settings = new QSettings(this);
    picIndex = 1;
    diagonalCMDouble = 1;

    timer->start(5);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePos()
{
    static QPoint lastCursorPosition;
    QPointF mouse = cursor->pos();
    QRectF view = ui->graphicsView->sceneRect();
    if(lastCursorPosition != mouse)    //make sure someone is touching the screen
    {
        if(mouse.x() - ui->graphicsView->x() > view.left() && mouse.x() - ui->graphicsView->x() < view.right() && mouse.y() - ui->graphicsView->y() > view.top() && mouse.y() - ui->graphicsView->y() < view.bottom())
        {
            ui->graphicsView->scene()->addEllipse(mouse.x() - ui->graphicsView->x(), mouse.y() - ui->graphicsView->y(), 3, 3, QPen(), QBrush(Qt::red));
            dataListRaw.append(QPoint(mouse.x() - ui->graphicsView->x(), mouse.y() - ui->graphicsView->y()));
        }
        else
        {
            qDebug() << "Touch outside of the scene view!";
        }
        lastCursorPosition = mouse.toPoint();
    }
}

void MainWindow::calcPPCM()
{
    calc->calculatePPCM(this->width(), this->height(), diagonalCMDouble);
}

void MainWindow::on_pbCalibrate_clicked()
{
    calcPPCM();

    loadSettings();
    dataListRaw.clear();

    if(ui->pbCalibrate->text() != "Reset")
    {
        ui->pbCalibrate->setText("Reset");
    }
}

void MainWindow::drawDataFieldInformation()
{
    scene->clear();
    scene->setSceneRect(0,0,ui->graphicsView->width(), ui->graphicsView->height());
    ui->graphicsView->resetTransform();

    calcPPCM();

    for(int i=0; i<ui->graphicsView->width();i = i + (int)calc->getPPCM())
    {
        scene->addLine(i, 0, i, ui->graphicsView->height(), QPen(QBrush(Qt::gray), 1)); //vertical lines
    }
    for(int i=0; i<ui->graphicsView->height();i = i+ (int)calc->getPPCM())
    {
        scene->addLine(0, i, ui->graphicsView->width(), i, QPen(QBrush(Qt::gray), 1));  //horizontal lines
    }

    //Add date to data field
    QDate date;
    QGraphicsSimpleTextItem * dateItem = new QGraphicsSimpleTextItem;
    dateItem->setText(date.currentDate().toString("MMM dd yyyy"));
    dateItem->setPos(0,0);
    scene->addItem(dateItem);

    //Add patient info to data field
    QGraphicsSimpleTextItem * patientInfo = new QGraphicsSimpleTextItem;
    patientInfo->setText(patientInfoString);
    patientInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50, 0);
    scene->addItem(patientInfo);

    //Add test info to data field
    QGraphicsSimpleTextItem * testInfo = new QGraphicsSimpleTextItem;
    testInfo->setText(testInfoString);
    testInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50 + patientInfo->boundingRect().width() + 50, 0);
    scene->addItem(testInfo);

    //Add trial (index) number
    QString trialString;
    trialString.append("Trial: ");
    trialString.append(QString::number(picIndex).rightJustified(2,'0'));
    QGraphicsSimpleTextItem * trialInfo = new QGraphicsSimpleTextItem;
    trialInfo->setText(trialString);
    trialInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50 + patientInfo->boundingRect().width() + 50 + testInfo->boundingRect().width() + 50, 0);
    scene->addItem(trialInfo);

    QList<QGraphicsItem *> items = scene->items();
    foreach(QGraphicsItem *i, items)
    {
        i->setFlag(QGraphicsItem::ItemIgnoresTransformations);
    }
    qDebug() << "Redrew data field static components";
}

void MainWindow::on_pbSaveData_clicked()
{
    timer->stop();  //pause the data-gathering
    ui->graphicsView->viewport()->update(); //update data field

    QDir photoDir("/mnt/sdcard/thumbdata");
    if(!photoDir.exists())
    {
        if(photoDir.mkdir("/mnt/sdcard/thumbdata") == false)    //if couldn't make dir
        {
            errorDialog = new ErrorDialog(this);
            errorDialog->exec();
            qDebug() << "Error: Could not find or create the folder to save the data in.";
        }
    }

    QString fileName = photoDir.absolutePath() + "/" + patientInfoString + "-" + testInfoString + QString::number(picIndex).rightJustified(2,'0') + ".png";
    QPixmap pixMap = QPixmap::grabWidget(ui->graphicsView);
    if(pixMap.save(fileName))
    {
        savedDialog = new SavedDialog(this);
        savedDialog->exec();
        qDebug() << "Info: Picture saved as " + fileName;
    }
    else
    {
        errorDialog = new ErrorDialog(this);
        errorDialog->exec();
        qDebug() << "Error: Couldn't save the pixmap";
    }

    picIndex++;

    timer->start(); //resume the data-gathering
}

void MainWindow::loadSettings()
{
    patientInfoString = settings->value("patientInfoString", "Patient Info").toString();
    testInfoString = settings->value("testInfoString", "Test Info").toString();
    diagonalCMDouble = settings->value("diagonalCM", 1).toDouble();
    qDebug() << "Settings loaded in MainWindow";

    drawDataFieldInformation(); //refresh the display to reflect updates
}

void MainWindow::on_pbSettings_clicked()
{
    loadSettings(); //fix CTD bug?
    settingsDialog = new SettingsDialog(patientInfoString, testInfoString, diagonalCMDouble, this);
    connect(settingsDialog, SIGNAL(patientInfo(QString)), this, SLOT(patientInfo(QString)));
    connect(settingsDialog, SIGNAL(testInfo(QString)), this, SLOT(testInfo(QString)));
    connect(settingsDialog, SIGNAL(diagonalCM(double)), this, SLOT(diagonalCM(double)));
    connect(settingsDialog, SIGNAL(accepted()), this, SLOT(resetPicIndex()));
    connect(settingsDialog, SIGNAL(accepted()), timer, SLOT(start()));
    connect(settingsDialog, SIGNAL(rejected()), timer, SLOT(start()));
    timer->stop();  //pause the data-gathering
    settingsDialog->exec();
}

void MainWindow::resetPicIndex()
{
    picIndex = 1;   //reset counter
    loadSettings(); //load the settings
    qDebug() << "Reset counter and called loadSettings()";
}

void MainWindow::patientInfo(QString patient)
{
    patientInfoString = patient;
    settings->setValue("patientInfoString", patientInfoString);
    settings->sync();
    qDebug() << "Patient info copied from Settings dialog";
}

void MainWindow::testInfo(QString test)
{
    testInfoString = test;
    settings->setValue("testInfoString", testInfoString);
    settings->sync();
    qDebug() << "Test info copied from Settings dialog";
}

void MainWindow::diagonalCM(double cm)
{
    diagonalCMDouble = cm;
    settings->setValue("diagonalCM", diagonalCMDouble);
    settings->sync();
    qDebug() << "diagonalCMDouble copied from Settings dialog";
}

QPointF MainWindow::calcCircle()
{
    //Prep work first, including gathering of data points
    QPointF center;
    center.setX(-1);
    center.setY(-1);

    QPointF roughCenter;
    roughCenter.setX(-1);
    roughCenter.setY(-1);

    int sectionBreak = dataListRaw.count()/10;  //break the datalist into 10 sections

    QList<QPointF> roughCenterList;  //hold all calculated center points

    qDebug() << "---------- Starting to calculate center points ----------";
    qDebug() << "dataListRaw count: " << dataListRaw.count();
    for(int i= 0; i <dataListRaw.count() - 2;i++)
    {
        qDebug() << "Low: " << i << ", High: " << (i + 2);
        QPointF a = dataListRaw.at(i);
        QPointF b = dataListRaw.at(i+1);
        QPointF c = dataListRaw.at(i+2);
        if(a.x() != b.x() && b.x() != c.x() && a.x() != c.x() && a.y() != b.y() && b.y() != c.y() && a.y() != c.y())
        {
            QPointF cP = calcCenter(a,b,c);
            if(cP.x() < - 3000 || cP.x() > 3000 || cP.y() < 0 || cP.y() > 3000)
            {
                qDebug() << "Ignoring centerpoint at " << cP << " for being too far away from a reasonable value!";
            }
            else
            {
             roughCenterList.append(cP);
            }
        }
    }

    qDebug() << "---------- Finished calculating center points ----------";

    roughCenter = calcAveragePoint(roughCenterList);  //Calculate the rough average center point

    QList<QPointF> centerList;

    foreach(QPointF centerPoint, roughCenterList)
    {
        centerList.append(centerPoint);
    }

    if(!centerList.isEmpty())
    {
        center = calcAveragePoint(centerList);
    }
    else
    {
        qDebug() << "ERROR: Accurate center point list is empty!";
    }

    //Draw information on screen
    QPointF testPoint = dataListRaw.at(sectionBreak*3);
    int radius = sqrt( ((center.x() - testPoint.x()) * (center.x() - testPoint.x())) + ((center.y() - testPoint.y()) * (center.y() - testPoint.y())) );
    scene->addEllipse(center.x()-radius, center.y()-radius, 2 * radius, 2 * radius, QPen(Qt::black), QBrush(QColor(0,255,0,64)));

    rom.setRadius((double)radius);
    rom.setCenterPoint(center);

    qDebug() << "Radius (px): " << radius;
    qDebug() << "PPCM: " << calc->getPPCM();

    return center;
}

QPointF MainWindow::calcCenter(QPointF a, QPointF b, QPointF c)
{
    QPointF centerTemp;

    qDebug() << a << "; " << b << "; " << c;
    double yDelta0 = b.y() - a.y();
    double xDelta0 = b.x() - a.x();
    double yDelta1 = c.y() - b.y();
    double xDelta1 = c.x() - b.x();

    double slope0 = yDelta0/xDelta0;
    double slope1 = yDelta1/xDelta1;
    double xD = 0;
    double yD = 0;

    xD = ( (slope0 * slope1 * (a.y() - c.y())) + (slope1 * (a.x() + b.x())) - (slope0 * (b.x() + c.x())) ) / (2.0 *(slope1 - slope0));
    yD = -1.0 * (xD - ((a.x() + b.x()) / 2 )) / slope0 + ((a.y() +b.y()) / 2);

    centerTemp.setX((int)xD);
    centerTemp.setY((int)yD);

    qDebug() << "Calculated center here: " << centerTemp;
    return centerTemp;
}

double MainWindow::calcROM()    //calculate the Range of Motion
{
    double romDegrees = -1;

    calcCircle();

    QPointF furthestPoint = QPointF(-1, -1);
    QPoint lastPoint = QPoint(0,0);

    foreach(QPoint p, dataListRaw)  //find the furthest point down
    {
        if(p.y() >= lastPoint.y())
        {
            furthestPoint.setX(p.x());
            furthestPoint.setY(p.y());
            lastPoint = p;
        }
        else
        {

        }
    }

    scene->addLine(rom.getCenterPoint().x(), rom.getCenterPoint().y(), furthestPoint.x(), furthestPoint.y(), QPen(Qt::blue));
    qDebug() << "Furthest Point: " << furthestPoint;

    QPointF verticalPoint = rom.getCenterPoint();

    verticalPoint.setY(verticalPoint.y() - rom.getRadius());
    scene->addLine(rom.getCenterPoint().x(), rom.getCenterPoint().y(), verticalPoint.x(), verticalPoint.y(), QPen(Qt::blue));
    qDebug() << "Vertical Point: " << verticalPoint;

    double deltaX = verticalPoint.x() - furthestPoint.x();
    double deltaY = verticalPoint.y() - furthestPoint.y();

    double chordLength = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    double thetaR = qAcos( ( (chordLength * chordLength) - (2 * (rom.getRadius() * rom.getRadius())) ) / ( -2 * (rom.getRadius() * rom.getRadius())) );

    double thetaD = 180.0 * thetaR / M_PI;

    romDegrees = thetaD;

    qDebug() << "Range of Motion degrees: " << romDegrees;

    return romDegrees;
}

void MainWindow::on_pbAnalyze_clicked()
{
    calcROM();
}

double MainWindow::calcDistance(QPointF a, QPointF b)
{
    double deltaX = a.x() - b.x();
    double deltaY = a.y() - b.y();

    double d = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    return d;
}

double MainWindow::calcDistance(QPoint a, QPoint b)
{
    double deltaX = (double)a.x() - (double)b.x();
    double deltaY = (double)a.y() - (double)b.y();

    double d = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    return d;
}

QPointF MainWindow::calcAveragePoint(QList<QPointF> l)
{

    qDebug() << "---------- Starting to calculate average point ----------";
    QPointF avgPnt = QPointF(0,0);

    foreach(QPointF p, l)
    {
        avgPnt.setX(avgPnt.x() + p.x());
        avgPnt.setY(avgPnt.y() + p.y());
    }

    avgPnt.setX(avgPnt.x() / (double)l.count());
    avgPnt.setY(avgPnt.y() / (double)l.count());
    qDebug() << "Average point: " << avgPnt;
    qDebug() << "---------- Calculated average point ----------";
    return avgPnt;
}
<commit_msg>Removed some of the ineffective center point finding algorithm<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QImage>
#include <QtDebug>
#include <QDir>
#include <QMessageBox>
#include <qmath.h>
#include <math.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString versionString;
    versionString.append(APP_VERSION);
    qDebug() << versionString;
    ui->labVersion->setText("Version: " + versionString);
    cursor = new QCursor();
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updatePos()));

    scene = new QGraphicsScene(ui->graphicsView);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    calc = new QPixelCalculator(this);

    patientInfoString = "PatientInfo";
    testInfoString = "TestInfo";
    settings = new QSettings(this);
    picIndex = 1;
    diagonalCMDouble = 1;

    timer->start(5);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updatePos()
{
    static QPoint lastCursorPosition;
    QPointF mouse = cursor->pos();
    QRectF view = ui->graphicsView->sceneRect();
    if(lastCursorPosition != mouse)    //make sure someone is touching the screen
    {
        if(mouse.x() - ui->graphicsView->x() > view.left() && mouse.x() - ui->graphicsView->x() < view.right() && mouse.y() - ui->graphicsView->y() > view.top() && mouse.y() - ui->graphicsView->y() < view.bottom())
        {
            ui->graphicsView->scene()->addEllipse(mouse.x() - ui->graphicsView->x(), mouse.y() - ui->graphicsView->y(), 3, 3, QPen(), QBrush(Qt::red));
            dataListRaw.append(QPoint(mouse.x() - ui->graphicsView->x(), mouse.y() - ui->graphicsView->y()));
        }
        else
        {
            qDebug() << "Touch outside of the scene view!";
        }
        lastCursorPosition = mouse.toPoint();
    }
}

void MainWindow::calcPPCM()
{
    calc->calculatePPCM(this->width(), this->height(), diagonalCMDouble);
}

void MainWindow::on_pbCalibrate_clicked()
{
    calcPPCM();

    loadSettings();
    dataListRaw.clear();

    if(ui->pbCalibrate->text() != "Reset")
    {
        ui->pbCalibrate->setText("Reset");
    }
}

void MainWindow::drawDataFieldInformation()
{
    scene->clear();
    scene->setSceneRect(0,0,ui->graphicsView->width(), ui->graphicsView->height());
    ui->graphicsView->resetTransform();

    calcPPCM();

    for(int i=0; i<ui->graphicsView->width();i = i + (int)calc->getPPCM())
    {
        scene->addLine(i, 0, i, ui->graphicsView->height(), QPen(QBrush(Qt::gray), 1)); //vertical lines
    }
    for(int i=0; i<ui->graphicsView->height();i = i+ (int)calc->getPPCM())
    {
        scene->addLine(0, i, ui->graphicsView->width(), i, QPen(QBrush(Qt::gray), 1));  //horizontal lines
    }

    //Add date to data field
    QDate date;
    QGraphicsSimpleTextItem * dateItem = new QGraphicsSimpleTextItem;
    dateItem->setText(date.currentDate().toString("MMM dd yyyy"));
    dateItem->setPos(0,0);
    scene->addItem(dateItem);

    //Add patient info to data field
    QGraphicsSimpleTextItem * patientInfo = new QGraphicsSimpleTextItem;
    patientInfo->setText(patientInfoString);
    patientInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50, 0);
    scene->addItem(patientInfo);

    //Add test info to data field
    QGraphicsSimpleTextItem * testInfo = new QGraphicsSimpleTextItem;
    testInfo->setText(testInfoString);
    testInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50 + patientInfo->boundingRect().width() + 50, 0);
    scene->addItem(testInfo);

    //Add trial (index) number
    QString trialString;
    trialString.append("Trial: ");
    trialString.append(QString::number(picIndex).rightJustified(2,'0'));
    QGraphicsSimpleTextItem * trialInfo = new QGraphicsSimpleTextItem;
    trialInfo->setText(trialString);
    trialInfo->setPos(dateItem->boundingRect().x() + dateItem->boundingRect().width() + 50 + patientInfo->boundingRect().width() + 50 + testInfo->boundingRect().width() + 50, 0);
    scene->addItem(trialInfo);

    QList<QGraphicsItem *> items = scene->items();
    foreach(QGraphicsItem *i, items)
    {
        i->setFlag(QGraphicsItem::ItemIgnoresTransformations);
    }
    qDebug() << "Redrew data field static components";
}

void MainWindow::on_pbSaveData_clicked()
{
    timer->stop();  //pause the data-gathering
    ui->graphicsView->viewport()->update(); //update data field

    QDir photoDir("/mnt/sdcard/thumbdata");
    if(!photoDir.exists())
    {
        if(photoDir.mkdir("/mnt/sdcard/thumbdata") == false)    //if couldn't make dir
        {
            errorDialog = new ErrorDialog(this);
            errorDialog->exec();
            qDebug() << "Error: Could not find or create the folder to save the data in.";
        }
    }

    QString fileName = photoDir.absolutePath() + "/" + patientInfoString + "-" + testInfoString + QString::number(picIndex).rightJustified(2,'0') + ".png";
    QPixmap pixMap = QPixmap::grabWidget(ui->graphicsView);
    if(pixMap.save(fileName))
    {
        savedDialog = new SavedDialog(this);
        savedDialog->exec();
        qDebug() << "Info: Picture saved as " + fileName;
    }
    else
    {
        errorDialog = new ErrorDialog(this);
        errorDialog->exec();
        qDebug() << "Error: Couldn't save the pixmap";
    }

    picIndex++;

    timer->start(); //resume the data-gathering
}

void MainWindow::loadSettings()
{
    patientInfoString = settings->value("patientInfoString", "Patient Info").toString();
    testInfoString = settings->value("testInfoString", "Test Info").toString();
    diagonalCMDouble = settings->value("diagonalCM", 1).toDouble();
    qDebug() << "Settings loaded in MainWindow";

    drawDataFieldInformation(); //refresh the display to reflect updates
}

void MainWindow::on_pbSettings_clicked()
{
    loadSettings(); //fix CTD bug?
    settingsDialog = new SettingsDialog(patientInfoString, testInfoString, diagonalCMDouble, this);
    connect(settingsDialog, SIGNAL(patientInfo(QString)), this, SLOT(patientInfo(QString)));
    connect(settingsDialog, SIGNAL(testInfo(QString)), this, SLOT(testInfo(QString)));
    connect(settingsDialog, SIGNAL(diagonalCM(double)), this, SLOT(diagonalCM(double)));
    connect(settingsDialog, SIGNAL(accepted()), this, SLOT(resetPicIndex()));
    connect(settingsDialog, SIGNAL(accepted()), timer, SLOT(start()));
    connect(settingsDialog, SIGNAL(rejected()), timer, SLOT(start()));
    timer->stop();  //pause the data-gathering
    settingsDialog->exec();
}

void MainWindow::resetPicIndex()
{
    picIndex = 1;   //reset counter
    loadSettings(); //load the settings
    qDebug() << "Reset counter and called loadSettings()";
}

void MainWindow::patientInfo(QString patient)
{
    patientInfoString = patient;
    settings->setValue("patientInfoString", patientInfoString);
    settings->sync();
    qDebug() << "Patient info copied from Settings dialog";
}

void MainWindow::testInfo(QString test)
{
    testInfoString = test;
    settings->setValue("testInfoString", testInfoString);
    settings->sync();
    qDebug() << "Test info copied from Settings dialog";
}

void MainWindow::diagonalCM(double cm)
{
    diagonalCMDouble = cm;
    settings->setValue("diagonalCM", diagonalCMDouble);
    settings->sync();
    qDebug() << "diagonalCMDouble copied from Settings dialog";
}

QPointF MainWindow::calcCircle()
{
    //Prep work first, including gathering of data points
    QPointF center;
    center.setX(-1);
    center.setY(-1);

    QPointF roughCenter;
    roughCenter.setX(-1);
    roughCenter.setY(-1);

    int sectionBreak = dataListRaw.count()/10;  //break the datalist into 10 sections

    QList<QPointF> roughCenterList;  //hold all calculated center points

    qDebug() << "---------- Starting to calculate center points ----------";
    qDebug() << "dataListRaw count: " << dataListRaw.count();
    for(int i= 0; i < dataListRaw.count();i++)
    {
        QPointF a = dataListRaw.at(i);
        QPointF b = dataListRaw.at(i+1);
        QPointF c = dataListRaw.at(i+2);
        if(a.x() != b.x() && b.x() != c.x() && a.x() != c.x() && a.y() != b.y() && b.y() != c.y() && a.y() != c.y())
        {
            QPointF cP = calcCenter(a,b,c);
            if(cP.x() < - 3000 || cP.x() > 3000 || cP.y() < 0 || cP.y() > 3000)
            {
                qDebug() << "Ignoring centerpoint at " << cP << " for being too far away from a reasonable value!";
            }
            else
            {
             roughCenterList.append(cP);
            }
        }
    }

    qDebug() << "---------- Finished calculating center points ----------";

    roughCenter = calcAveragePoint(roughCenterList);  //Calculate the rough average center point

    if(!roughCenterList.isEmpty())
    {
        center = calcAveragePoint(roughCenterList);
    }
    else
    {
        qDebug() << "ERROR: Center point list is empty!";
    }

    //Draw information on screen
    QPointF testPoint = dataListRaw.at(sectionBreak*3);
    int radius = sqrt( ((center.x() - testPoint.x()) * (center.x() - testPoint.x())) + ((center.y() - testPoint.y()) * (center.y() - testPoint.y())) );
    scene->addEllipse(center.x()-radius, center.y()-radius, 2 * radius, 2 * radius, QPen(Qt::black), QBrush(QColor(0,255,0,64)));

    rom.setRadius((double)radius);
    rom.setCenterPoint(center);

    qDebug() << "Radius (px): " << radius;
    qDebug() << "PPCM: " << calc->getPPCM();

    return center;
}

QPointF MainWindow::calcCenter(QPointF a, QPointF b, QPointF c)
{
    QPointF centerTemp;

    qDebug() << a << "; " << b << "; " << c;
    double yDelta0 = b.y() - a.y();
    double xDelta0 = b.x() - a.x();
    double yDelta1 = c.y() - b.y();
    double xDelta1 = c.x() - b.x();

    double slope0 = yDelta0/xDelta0;
    double slope1 = yDelta1/xDelta1;
    double xD = 0;
    double yD = 0;

    xD = ( (slope0 * slope1 * (a.y() - c.y())) + (slope1 * (a.x() + b.x())) - (slope0 * (b.x() + c.x())) ) / (2.0 *(slope1 - slope0));
    yD = -1.0 * (xD - ((a.x() + b.x()) / 2 )) / slope0 + ((a.y() +b.y()) / 2);

    centerTemp.setX((int)xD);
    centerTemp.setY((int)yD);

    qDebug() << "Calculated center here: " << centerTemp;
    return centerTemp;
}

double MainWindow::calcROM()    //calculate the Range of Motion
{
    double romDegrees = -1;

    calcCircle();

    QPointF furthestPoint = QPointF(-1, -1);
    QPoint lastPoint = QPoint(0,0);

    foreach(QPoint p, dataListRaw)  //find the furthest point down
    {
        if(p.y() >= lastPoint.y())
        {
            furthestPoint.setX(p.x());
            furthestPoint.setY(p.y());
            lastPoint = p;
        }
        else
        {

        }
    }

    scene->addLine(rom.getCenterPoint().x(), rom.getCenterPoint().y(), furthestPoint.x(), furthestPoint.y(), QPen(Qt::blue));
    qDebug() << "Furthest Point: " << furthestPoint;

    QPointF verticalPoint = rom.getCenterPoint();

    verticalPoint.setY(verticalPoint.y() - rom.getRadius());
    scene->addLine(rom.getCenterPoint().x(), rom.getCenterPoint().y(), verticalPoint.x(), verticalPoint.y(), QPen(Qt::blue));
    qDebug() << "Vertical Point: " << verticalPoint;

    double deltaX = verticalPoint.x() - furthestPoint.x();
    double deltaY = verticalPoint.y() - furthestPoint.y();

    double chordLength = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    double thetaR = qAcos( ( (chordLength * chordLength) - (2 * (rom.getRadius() * rom.getRadius())) ) / ( -2 * (rom.getRadius() * rom.getRadius())) );

    double thetaD = 180.0 * thetaR / M_PI;

    romDegrees = thetaD;

    qDebug() << "Range of Motion degrees: " << romDegrees;

    return romDegrees;
}

void MainWindow::on_pbAnalyze_clicked()
{
    calcROM();
}

double MainWindow::calcDistance(QPointF a, QPointF b)
{
    double deltaX = a.x() - b.x();
    double deltaY = a.y() - b.y();

    double d = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    return d;
}

double MainWindow::calcDistance(QPoint a, QPoint b)
{
    double deltaX = (double)a.x() - (double)b.x();
    double deltaY = (double)a.y() - (double)b.y();

    double d = sqrt( (deltaX * deltaX) + (deltaY * deltaY) );

    return d;
}

QPointF MainWindow::calcAveragePoint(QList<QPointF> l)
{

    qDebug() << "---------- Starting to calculate average point ----------";
    QPointF avgPnt = QPointF(0,0);

    foreach(QPointF p, l)
    {
        avgPnt.setX(avgPnt.x() + p.x());
        avgPnt.setY(avgPnt.y() + p.y());
    }

    avgPnt.setX(avgPnt.x() / (double)l.count());
    avgPnt.setY(avgPnt.y() / (double)l.count());
    qDebug() << "Average point: " << avgPnt;
    qDebug() << "---------- Calculated average point ----------";
    return avgPnt;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

#define TEST
//#define REAL

#define WINDOWS
//#define MAC

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::exit()
{
    close();
    qApp->quit();
}

void MainWindow::on_patchButton_clicked()
{
    if(searchKernelExtensionFile(&kernelFile))
    {
        //Display Warning Message
        int answer = QMessageBox::question(this, "Warning", "This will patch the kernel configuration file.\nAre you sure you want to procede ?", QMessageBox::Yes | QMessageBox::No);

        if (answer == QMessageBox::Yes)
        {
            patchKernelExtensionFile(&kernelFile);
        }
        else
        {
            return;
        }
    }
    else
    {
        return;
    }
}

void MainWindow::on_restoreButton_clicked()
{
    //Display Warning Message
    int answer = QMessageBox::question(this, "Warning", "This will restore the old configuration.\nAre you sure you want to procede ?", QMessageBox::Yes | QMessageBox::No);

    if (answer == QMessageBox::Yes)
    {

    }
    else
    {
        return;
    }
}

bool MainWindow::init()
{
    bool isInitOk = true;

    MainWindow::setWindowTitle (APP_NAME);

    //Search for compatibility
    if(isCompatibleVersion(getMBPModelVersion()))
    {
        isInitOk = true;
    }
    else
    {
        QMessageBox::information(this,"Mac not compatible","Sorry, your Mac is not compatible.\nThe application will close");
        isInitOk = false;
    }

    return isInitOk;
}

QString MainWindow::getMBPModelVersion()
{
    QString MBPModelVersion;
    QProcess process;

    //Execute commande line
    process.start("sysctl -n hw.model");

    //Wait forever until finished
    process.waitForFinished(-1);

    //Get command line output
    MBPModelVersion = process.readAllStandardOutput();

    //Remove carriage return ("\n") from string
    MBPModelVersion = MBPModelVersion.simplified();

    return MBPModelVersion;
}

//Parse system directory searching for AppleGraphicsPowerManagement.kext file
bool MainWindow::searchKernelExtensionFile(QFile* kernelExtensionFile)
{
    bool isFileFound;

#ifdef TEST
#ifdef MAC
    QDir kextPath("/Users/Julian/Documents/Dev/Projects/MBPMid2010_GPUFix/");
#endif
#ifdef WINDOWS
    QDir kextPath("C:/Users/jpoidevin/Desktop/Documents Pro/03 - Dev Temp/MBPMid2010_GPUFix/MBPMid2010_GPUFix/");
#endif
#endif
#ifdef REAL
    QDir kextPath("/System/Library/Extensions/AppleGraphicsPowerManagement.kext/");
#endif

    QStringList listOfFiles;

    //Print Current app directory
    qDebug() << "Current Dir :" <<kextPath.absolutePath();

    //Recursively search for "Info.plist" file in appPath
    QDirIterator it(kextPath.absolutePath(),
                    QStringList() << "Info.plist",
                    QDir::NoSymLinks | QDir::Files,
                    QDirIterator::Subdirectories);

    //Check if the file was found
    if(it.hasNext())
    {
        while(it.hasNext())
        {
            it.next();
            listOfFiles.push_back(it.filePath());
        }
    }

    //Print files found
    qDebug() << "Files found :"<< listOfFiles;

    if(listOfFiles.length() <= 1 && listOfFiles.length() > 0)
    {
        //qDebug() << "Moins de 1";
        kernelExtensionFile->setFileName(listOfFiles.at(0));
        isFileFound = true;
    }
    else
    {
        //qDebug () << "No file was found...";
        isFileFound = false;
    }

    //Start search manually and only allow loading of the perfect named file (or kext)
    if(!isFileFound)
    {
        QMessageBox::information(this,"File not found","Any corresponding file was found, please search for the file");

        //TODO : FileDialog won't let user brown into .kext files Contents
        QString dir = QFileDialog::getOpenFileName(this, tr("Open Info.plist file"),
                                                   "/System/Library/Extensions/AppleGraphicsPowerManagement.kext/",
                                                   "Property List Files (Info.plist)");
        if(!(dir.isNull()))
        {
            //kernelExtensionFile->setFileName(dir);
            isFileFound = true;
        }
        else
        {
            isFileFound = false;
        }
    }

    return isFileFound;
}

bool MainWindow::isCompatibleVersion(QString modelVersion)
{
    //Compare version with compatible versions of MBPs
    bool isCompatibleVersion;

#ifdef MAC

    //TODO : Search in a list
    if(modelVersion == "MacBookPro6,2")
    {
        isCompatibleVersion = true;
    }
    else
    {
        isCompatibleVersion = false;
    }

#endif
#ifdef WINDOWS
    isCompatibleVersion = true;
#endif

    return isCompatibleVersion;
}

void MainWindow::backupOldKernelExtension()
{
    //Save File to current location adding .bak extension
    //qDebug() << "File Name" << kernelFile.fileName();

    //Save original file in kernelExtension file folder
    QFile::copy(kernelFile.fileName(), kernelFile.fileName() + ".bak");
}

void MainWindow::patchKernelExtensionFile(QFile *kernelFile)
{
    //Modify Kernel Extension File to add fix explained here :
    //https://forums.macrumors.com/threads/gpu-kernel-panic-in-mid-2010-whats-the-best-fix.1890097/
    //Use QSettings ? : http://doc.qt.io/qt-5/qsettings.html
    //https://openclassrooms.com/courses/enregistrer-vos-options-avec-qsettings
    //http://stackoverflow.com/questions/20240511/qsettings-mac-and-plist-files
    //https://forum.qt.io/topic/37247/qsettings-with-systemscope-not-saving-plist-file-in-os-x-mavericks/6

    backupOldKernelExtension();

#ifdef MAC
#define PATCHED_FILE_PATH "/tmp/PatchedInfo.plist"
#endif
#ifdef WINDOWS
#define PATCHED_FILE_PATH "C:/temp/PatchedInfo.plist"
#endif

    //Copy file in tmp dir for patch
    QFile::copy(kernelFile->fileName(), PATCHED_FILE_PATH);

    QFile tmpFile(PATCHED_FILE_PATH);

    if(!tmpFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        qDebug() << "Could not open tmp File";
        return;
    }

    QXmlStreamReader xmlReader(&tmpFile);

    while(!xmlReader.atEnd() && !xmlReader.hasError())
    {
        QXmlStreamReader::TokenType token = xmlReader.readNext();
        if(token == QXmlStreamReader::StartElement)
        {
            //qDebug() << xmlReader.name();

            if(xmlReader.name().compare("key",Qt::CaseInsensitive) == 0)
            {
                qDebug() << "Found IOKitPersonalities";
            }

            if(xmlReader.name().compare("key", Qt::CaseInsensitive) == 0)
            {
               // qDebug() << "Found IOKitPersonalities";
            }
        }

        //Creating QSettings object. "NativeFormat" is for accessing XML-based .plist files.
        //QSettings settings(PATCHED_FILE_PATH, QSettings::NativeFormat);

        //Find a way to parse file to : IOKitPersonalities -> AGPM -> Machines -> MacBookPro6,2 -> Vendor10deDevice0a29
        //qDebug() << settings.value("IOKitPersonalities");
        //qDebug() << settings.allKeys();

        //Check if kernelFile is Writable
        //if(!settings.isWritable())
        //{
        //    //TODO : handle not writable file
        //    return;
        //}

        //if(settings.contains("LogControl"))
        //{
        //    qDebug() << "Contains Log Control";
        //}
        //else
        //{
        //    qDebug() << "Does not contains Log Control";
        //}
    }
}

int MainWindow::loadKernelExtension(QFile *kernelFile)
{
    //Use Kext Utility or command lines utils to load the file in Kernel
    //kextload

    //See here : http://osxdaily.com/2015/06/24/load-unload-kernel-extensions-mac-os-x/
    int Status = 0;

    return Status;
}

int MainWindow::restoreOldKernelExtension(QFile *kernelFile)
{
    //Restore.bak extension
    int Status = 0;

    //QFile::copy(kernelFile->fileName()  + ".bak", kernelFile->fileName());

    return Status;
}
<commit_msg>Playing around with XML parser<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

#define TEST
//#define REAL

//#define WINDOWS
#define MAC

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::exit()
{
    close();
    qApp->quit();
}

void MainWindow::on_patchButton_clicked()
{
    if(searchKernelExtensionFile(&kernelFile))
    {
        //Display Warning Message
        int answer = QMessageBox::question(this, "Warning", "This will patch the kernel configuration file.\nAre you sure you want to procede ?", QMessageBox::Yes | QMessageBox::No);

        if (answer == QMessageBox::Yes)
        {
            patchKernelExtensionFile(&kernelFile);
        }
        else
        {
            return;
        }
    }
    else
    {
        return;
    }
}

void MainWindow::on_restoreButton_clicked()
{
    //Display Warning Message
    int answer = QMessageBox::question(this, "Warning", "This will restore the old configuration.\nAre you sure you want to procede ?", QMessageBox::Yes | QMessageBox::No);

    if (answer == QMessageBox::Yes)
    {

    }
    else
    {
        return;
    }
}

bool MainWindow::init()
{
    bool isInitOk = true;

    MainWindow::setWindowTitle (APP_NAME);

    //Search for compatibility
    if(isCompatibleVersion(getMBPModelVersion()))
    {
        isInitOk = true;
    }
    else
    {
        QMessageBox::information(this,"Mac not compatible","Sorry, your Mac is not compatible.\nThe application will close");
        isInitOk = false;
    }

    return isInitOk;
}

QString MainWindow::getMBPModelVersion()
{
    QString MBPModelVersion;
    QProcess process;

    //Execute commande line
    process.start("sysctl -n hw.model");

    //Wait forever until finished
    process.waitForFinished(-1);

    //Get command line output
    MBPModelVersion = process.readAllStandardOutput();

    //Remove carriage return ("\n") from string
    MBPModelVersion = MBPModelVersion.simplified();

    return MBPModelVersion;
}

//Parse system directory searching for AppleGraphicsPowerManagement.kext file
bool MainWindow::searchKernelExtensionFile(QFile* kernelExtensionFile)
{
    bool isFileFound;

#ifdef TEST
#ifdef MAC
    QDir kextPath("/Users/Julian/Documents/Dev/Projects/MBPMid2010_GPUFix/");
#endif
#ifdef WINDOWS
    QDir kextPath("C:/Users/jpoidevin/Desktop/Documents Pro/03 - Dev Temp/MBPMid2010_GPUFix/MBPMid2010_GPUFix/");
#endif
#endif
#ifdef REAL
    QDir kextPath("/System/Library/Extensions/AppleGraphicsPowerManagement.kext/");
#endif

    QStringList listOfFiles;

    //Print Current app directory
    qDebug() << "Current Dir :" <<kextPath.absolutePath();

    //Recursively search for "Info.plist" file in appPath
    QDirIterator it(kextPath.absolutePath(),
                    QStringList() << "Info.plist",
                    QDir::NoSymLinks | QDir::Files,
                    QDirIterator::Subdirectories);

    //Check if the file was found
    if(it.hasNext())
    {
        while(it.hasNext())
        {
            it.next();
            listOfFiles.push_back(it.filePath());
        }
    }

    //Print files found
    qDebug() << "Files found :"<< listOfFiles;

    if(listOfFiles.length() <= 1 && listOfFiles.length() > 0)
    {
        //qDebug() << "Moins de 1";
        kernelExtensionFile->setFileName(listOfFiles.at(0));
        isFileFound = true;
    }
    else
    {
        //qDebug () << "No file was found...";
        isFileFound = false;
    }

    //Start search manually and only allow loading of the perfect named file (or kext)
    if(!isFileFound)
    {
        QMessageBox::information(this,"File not found","Any corresponding file was found, please search for the file");

        //TODO : FileDialog won't let user brown into .kext files Contents
        QString dir = QFileDialog::getOpenFileName(this, tr("Open Info.plist file"),
                                                   "/System/Library/Extensions/AppleGraphicsPowerManagement.kext/",
                                                   "Property List Files (Info.plist)");
        if(!(dir.isNull()))
        {
            //kernelExtensionFile->setFileName(dir);
            isFileFound = true;
        }
        else
        {
            isFileFound = false;
        }
    }

    return isFileFound;
}

bool MainWindow::isCompatibleVersion(QString modelVersion)
{
    //Compare version with compatible versions of MBPs
    bool isCompatibleVersion;

#ifdef MAC

    //TODO : Search in a list
    if(modelVersion == "MacBookPro6,2")
    {
        isCompatibleVersion = true;
    }
    else
    {
        isCompatibleVersion = false;
    }

#endif
#ifdef WINDOWS
    isCompatibleVersion = true;
#endif

    return isCompatibleVersion;
}

void MainWindow::backupOldKernelExtension()
{
    //Save File to current location adding .bak extension
    //qDebug() << "File Name" << kernelFile.fileName();

    //Save original file in kernelExtension file folder
    QFile::copy(kernelFile.fileName(), kernelFile.fileName() + ".bak");
}

void MainWindow::patchKernelExtensionFile(QFile *kernelFile)
{
    //Modify Kernel Extension File to add fix explained here :
    //https://forums.macrumors.com/threads/gpu-kernel-panic-in-mid-2010-whats-the-best-fix.1890097/
    //Use QSettings ? : http://doc.qt.io/qt-5/qsettings.html
    //https://openclassrooms.com/courses/enregistrer-vos-options-avec-qsettings
    //http://stackoverflow.com/questions/20240511/qsettings-mac-and-plist-files
    //https://forum.qt.io/topic/37247/qsettings-with-systemscope-not-saving-plist-file-in-os-x-mavericks/6

    backupOldKernelExtension();

#ifdef MAC
#define PATCHED_FILE_PATH "/tmp/PatchedInfo.plist"
#endif
#ifdef WINDOWS
#define PATCHED_FILE_PATH "C:/temp/PatchedInfo.plist"
#endif

    //Copy file in tmp dir for patch
    QFile::copy(kernelFile->fileName(), PATCHED_FILE_PATH);

    QFile tmpFile(PATCHED_FILE_PATH);

    if(!tmpFile.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        qDebug() << "Could not open tmp File";
        return;
    }

    QXmlStreamReader xmlReader(&tmpFile);

    if (xmlReader.readNextStartElement()) {
        if (xmlReader.name() == "plist"){

            while(xmlReader.readNextStartElement())
            {
                if(xmlReader.name() == "dict")
                {
                    while(xmlReader.readNextStartElement())
                    {
                        if(xmlReader.name() == "key")
                        {
                            //qDebug() << xmlReader.readElementText();
                            if(xmlReader.readElementText() == "AGPM")
                            {
                                while(xmlReader.readNextStartElement())
                                {
                                    if(xmlReader.name() == "dict")
                                    {
                                        while(xmlReader.readNextStartElement())
                                        {
                                            xmlReader.readNext();
                                            xmlReader.readNext();

                                            if(xmlReader.name() == "key")
                                            {
                                                qDebug() << xmlReader.readElementText();
                                            }
                                        }
                                    }
                                }

                            }

                        }

                    }
                }
                else
                {
                    xmlReader.skipCurrentElement();
                }
            }
        }
    }

    //    while(!xmlReader.atEnd() && !xmlReader.hasError())
    //    {
    //        QXmlStreamReader::TokenType token = xmlReader.readNext();
    //        if(token == QXmlStreamReader::StartElement)
    //        {
    //            //qDebug() << xmlReader.name();

    //            if(xmlReader.name().compare(static_cast<QString>("key"),Qt::CaseInsensitive) == 0)
    //            {
    //                qDebug() << "Found IOKitPersonalities";
    //            }
    //        }
    //    }

    //Creating QSettings object. "NativeFormat" is for accessing XML-based .plist files.
    //QSettings settings(PATCHED_FILE_PATH, QSettings::NativeFormat);

    //Find a way to parse file to : IOKitPersonalities -> AGPM -> Machines -> MacBookPro6,2 -> Vendor10deDevice0a29
    //qDebug() << settings.value("IOKitPersonalities");
    //qDebug() << settings.allKeys();

    //Check if kernelFile is Writable
    //if(!settings.isWritable())
    //{
    //    //TODO : handle not writable file
    //    return;
    //}

    //if(settings.contains("LogControl"))
    //{
    //    qDebug() << "Contains Log Control";
    //}
    //else
    //{
    //    qDebug() << "Does not contains Log Control";
    //}

}

int MainWindow::loadKernelExtension(QFile *kernelFile)
{
    //Use Kext Utility or command lines utils to load the file in Kernel
    //kextload

    //See here : http://osxdaily.com/2015/06/24/load-unload-kernel-extensions-mac-os-x/
    int Status = 0;

    return Status;
}

int MainWindow::restoreOldKernelExtension(QFile *kernelFile)
{
    //Restore.bak extension
    int Status = 0;

    //QFile::copy(kernelFile->fileName()  + ".bak", kernelFile->fileName());

    return Status;
}
<|endoftext|>


<commit_before>#include "scenewidget.h"
#include <QSurfaceFormat>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>

SceneWidget::SceneWidget(QWidget *parent) :
    QOpenGLWidget(parent)
{
    // Set opengl version & profile
    QSurfaceFormat format;

    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setVersion(3, 2);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setDepthBufferSize(24);
    format.setSamples(4);

    setFormat(format);
}

SceneWidget::~SceneWidget()
{

}

void SceneWidget::initializeGL()
{
    // Init opengl
    bool success = initializeOpenGLFunctions();

    // Check if opengl init was successfull
    if (!success)
        throw std::runtime_error("Could not load OpenGL functions.\nDo you have OpenGL v3.2?");

    // Print version info
    std::clog << "OpenGL version: " << glGetString(GL_VERSION) <<
                 "\nGLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) <<
                 "\nRenderer: " << glGetString(GL_RENDERER) <<
                 "\nVendor: " << glGetString(GL_VENDOR) << '\n' << std::endl;

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    initProgram();
    initData();
}

void SceneWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(m_program);
    glBindVertexArray(m_vao);

    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(0));

    glBindVertexArray(0);
    glUseProgram(0);
}

void SceneWidget::resizeGL(int w, int h)
{
    // Adjust viewport
    glViewport(0, 0, w, h);
}

void SceneWidget::initProgram()
{
    GLuint vs = compileShader("../res/shader.vert", GL_VERTEX_SHADER);
    GLuint fs = compileShader("../res/shader.frag", GL_FRAGMENT_SHADER);

    m_program = glCreateProgram();

    glAttachShader(m_program, vs);
    glAttachShader(m_program, fs);

    glLinkProgram(m_program);
    checkShaderErrors(m_program, true, GL_LINK_STATUS, "Could not link program");

    glValidateProgram(m_program);
    checkShaderErrors(m_program, true, GL_VALIDATE_STATUS, "Could not validate program");

    glDetachShader(m_program, vs);
    glDetachShader(m_program, fs);

    glDeleteShader(vs);
    glDeleteShader(fs);
}

std::string SceneWidget::getFileContents(const std::string &path) const
{
    std::ifstream file(path);
    if (!file.is_open())
        throw std::runtime_error("Could not open file: " + path);

    std::ostringstream oss;
    oss << file.rdbuf();
    return oss.str();
}

void SceneWidget::checkShaderErrors(GLuint shader, bool isProgram, GLenum param, const std::string &errorMsg)
{
    GLint status;
    if (isProgram)
        glGetProgramiv(shader, param, &status);
    else
        glGetShaderiv(shader, param, &status);

    if (status)
        return; // No errors

    GLint logLength;
    if (isProgram)
        glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &logLength);
    else
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);

    GLchar *buffer = new GLchar[logLength];
    if (isProgram)
        glGetProgramInfoLog(shader, logLength, nullptr, buffer);
    else
        glGetShaderInfoLog(shader, logLength, nullptr, buffer);

    std::ostringstream msgStream;
    msgStream << errorMsg << ":\n" << buffer;
    std::string msg = msgStream.str();

    delete[] buffer;
    throw std::runtime_error(msg);
}

GLuint SceneWidget::compileShader(const std::string &path, GLenum type)
{
    std::string typeStr;
    switch (type)
    {
    case GL_VERTEX_SHADER:
        typeStr = "vertex";
        break;
    case GL_FRAGMENT_SHADER:
        typeStr = "fragment";
        break;
    default:
        typeStr = "unknown";
        break;
    }

    GLuint shader = glCreateShader(type);

    std::string source = getFileContents(path);
    const GLchar *sourceCStr = source.c_str();

    glShaderSource(shader, 1, &sourceCStr, nullptr);
    glCompileShader(shader);
    checkShaderErrors(shader, false, GL_COMPILE_STATUS, "Could not compile " + typeStr + " shader");

    return shader;
}

void SceneWidget::initData()
{
    // Data
    GLfloat data[] =
    {
        // Front face
        -1.0f, -1.0f, +1.0f,
        -1.0f, +1.0f, +1.0f,
        +1.0f, +1.0f, +1.0f,
        +1.0f, -1.0f, +1.0f,

        // Right face
        +1.0f, -1.0f, +1.0f,
        +1.0f, +1.0f, +1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,

        // Top face
        -1.0f, +1.0f, +1.0f,
        -1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, +1.0f,

        // Back face
        -1.0f, -1.0f, -1.0f,
        -1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,

        // Left face
        -1.0f, -1.0f, +1.0f,
        -1.0f, +1.0f, +1.0f,
        -1.0f, +1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,

        // Bottom face
        -1.0f, -1.0f, +1.0f,
        -1.0f, -1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,
        +1.0f, -1.0f, +1.0f,
    };

    // Indices
    GLushort indices[] =
    {
        // Front face
        0, 1, 2,
        0, 2, 3,

        // Right face
        4, 5, 6,
        4, 6, 7,

        // Top face
        8, 9, 10,
        8, 10, 11,

        // Back face
        12, 14, 13,
        12, 15, 14,

        // Left face
        16, 18, 17,
        16, 19, 18,

        // Bottom face
        20, 22, 21,
        20, 23, 22,
    };

    // Create and bind vao
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    // Create and bind position vbo
    glGenBuffers(1, &m_positionVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_positionVbo);

    // Create and bind indices vbo
    glGenBuffers(1, &m_indicesVbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indicesVbo);

    // Fill position buffer & associate with attrib
    glBufferData(GL_ARRAY_BUFFER, sizeof data, data, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(0));

    // Fill indices buffer
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof indices, indices, GL_STATIC_DRAW);

    // Cleanup
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
<commit_msg>Enabled face culling<commit_after>#include "scenewidget.h"
#include <QSurfaceFormat>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>

SceneWidget::SceneWidget(QWidget *parent) :
    QOpenGLWidget(parent)
{
    // Set opengl version & profile
    QSurfaceFormat format;

    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setVersion(3, 2);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setDepthBufferSize(24);
    format.setSamples(4);

    setFormat(format);
}

SceneWidget::~SceneWidget()
{

}

void SceneWidget::initializeGL()
{
    // Init opengl
    bool success = initializeOpenGLFunctions();

    // Check if opengl init was successfull
    if (!success)
        throw std::runtime_error("Could not load OpenGL functions.\nDo you have OpenGL v3.2?");

    // Print version info
    std::clog << "OpenGL version: " << glGetString(GL_VERSION) <<
                 "\nGLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) <<
                 "\nRenderer: " << glGetString(GL_RENDERER) <<
                 "\nVendor: " << glGetString(GL_VENDOR) << '\n' << std::endl;

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    // Enable face culling
    glEnable(GL_CULL_FACE);
    glFrontFace(GL_CW);
    glCullFace(GL_BACK);

    initProgram();
    initData();
}

void SceneWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(m_program);
    glBindVertexArray(m_vao);

    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(0));

    glBindVertexArray(0);
    glUseProgram(0);
}

void SceneWidget::resizeGL(int w, int h)
{
    // Adjust viewport
    glViewport(0, 0, w, h);
}

void SceneWidget::initProgram()
{
    GLuint vs = compileShader("../res/shader.vert", GL_VERTEX_SHADER);
    GLuint fs = compileShader("../res/shader.frag", GL_FRAGMENT_SHADER);

    m_program = glCreateProgram();

    glAttachShader(m_program, vs);
    glAttachShader(m_program, fs);

    glLinkProgram(m_program);
    checkShaderErrors(m_program, true, GL_LINK_STATUS, "Could not link program");

    glValidateProgram(m_program);
    checkShaderErrors(m_program, true, GL_VALIDATE_STATUS, "Could not validate program");

    glDetachShader(m_program, vs);
    glDetachShader(m_program, fs);

    glDeleteShader(vs);
    glDeleteShader(fs);
}

std::string SceneWidget::getFileContents(const std::string &path) const
{
    std::ifstream file(path);
    if (!file.is_open())
        throw std::runtime_error("Could not open file: " + path);

    std::ostringstream oss;
    oss << file.rdbuf();
    return oss.str();
}

void SceneWidget::checkShaderErrors(GLuint shader, bool isProgram, GLenum param, const std::string &errorMsg)
{
    GLint status;
    if (isProgram)
        glGetProgramiv(shader, param, &status);
    else
        glGetShaderiv(shader, param, &status);

    if (status)
        return; // No errors

    GLint logLength;
    if (isProgram)
        glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &logLength);
    else
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);

    GLchar *buffer = new GLchar[logLength];
    if (isProgram)
        glGetProgramInfoLog(shader, logLength, nullptr, buffer);
    else
        glGetShaderInfoLog(shader, logLength, nullptr, buffer);

    std::ostringstream msgStream;
    msgStream << errorMsg << ":\n" << buffer;
    std::string msg = msgStream.str();

    delete[] buffer;
    throw std::runtime_error(msg);
}

GLuint SceneWidget::compileShader(const std::string &path, GLenum type)
{
    std::string typeStr;
    switch (type)
    {
    case GL_VERTEX_SHADER:
        typeStr = "vertex";
        break;
    case GL_FRAGMENT_SHADER:
        typeStr = "fragment";
        break;
    default:
        typeStr = "unknown";
        break;
    }

    GLuint shader = glCreateShader(type);

    std::string source = getFileContents(path);
    const GLchar *sourceCStr = source.c_str();

    glShaderSource(shader, 1, &sourceCStr, nullptr);
    glCompileShader(shader);
    checkShaderErrors(shader, false, GL_COMPILE_STATUS, "Could not compile " + typeStr + " shader");

    return shader;
}

void SceneWidget::initData()
{
    // Data
    GLfloat data[] =
    {
        // Front face
        -1.0f, -1.0f, +1.0f,
        -1.0f, +1.0f, +1.0f,
        +1.0f, +1.0f, +1.0f,
        +1.0f, -1.0f, +1.0f,

        // Right face
        +1.0f, -1.0f, +1.0f,
        +1.0f, +1.0f, +1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,

        // Top face
        -1.0f, +1.0f, +1.0f,
        -1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, +1.0f,

        // Back face
        -1.0f, -1.0f, -1.0f,
        -1.0f, +1.0f, -1.0f,
        +1.0f, +1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,

        // Left face
        -1.0f, -1.0f, +1.0f,
        -1.0f, +1.0f, +1.0f,
        -1.0f, +1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,

        // Bottom face
        -1.0f, -1.0f, +1.0f,
        -1.0f, -1.0f, -1.0f,
        +1.0f, -1.0f, -1.0f,
        +1.0f, -1.0f, +1.0f,
    };

    // Indices
    GLushort indices[] =
    {
        // Front face
        0, 1, 2,
        0, 2, 3,

        // Right face
        4, 5, 6,
        4, 6, 7,

        // Top face
        8, 9, 10,
        8, 10, 11,

        // Back face
        12, 14, 13,
        12, 15, 14,

        // Left face
        16, 18, 17,
        16, 19, 18,

        // Bottom face
        20, 22, 21,
        20, 23, 22,
    };

    // Create and bind vao
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    // Create and bind position vbo
    glGenBuffers(1, &m_positionVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_positionVbo);

    // Create and bind indices vbo
    glGenBuffers(1, &m_indicesVbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indicesVbo);

    // Fill position buffer & associate with attrib
    glBufferData(GL_ARRAY_BUFFER, sizeof data, data, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(0));

    // Fill indices buffer
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof indices, indices, GL_STATIC_DRAW);

    // Cleanup
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkDataArraySelection.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkDataArraySelection.h"
#include "vtkObjectFactory.h"

#include <vector>
#include <string>
#include <algorithm>

vtkCxxRevisionMacro(vtkDataArraySelection, "1.7");
vtkStandardNewMacro(vtkDataArraySelection);

class vtkDataArraySelectionArrayNamesType: public vtkstd::vector<vtkstd::string> {};
class vtkDataArraySelectionArraySettingsType: public vtkstd::vector<int> {};

//----------------------------------------------------------------------------
vtkDataArraySelection::vtkDataArraySelection()
{
  this->ArrayNames = new vtkDataArraySelectionArrayNamesType;
  this->ArraySettings = new vtkDataArraySelectionArraySettingsType;
}

//----------------------------------------------------------------------------
vtkDataArraySelection::~vtkDataArraySelection()
{
  delete this->ArraySettings;
  delete this->ArrayNames;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Number of Arrays: " << this->GetNumberOfArrays() << "\n";
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::EnableArray(const char* name)
{
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), name);
  if(i != this->ArrayNames->end())
    {
    int& setting = (*this->ArraySettings)[i-this->ArrayNames->begin()];
    if(!setting)
      {
      setting = 1;
      this->Modified();
      }
    }
  else
    {
    this->ArrayNames->push_back(name);
    this->ArraySettings->push_back(1);
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::DisableArray(const char* name)
{
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), name);
  if(i != this->ArrayNames->end())
    {
    int& setting = (*this->ArraySettings)[i - this->ArrayNames->begin()];
    if(setting)
      {
      setting = 0;
      this->Modified();
      }
    }
  else
    {
    this->ArrayNames->push_back(name);
    this->ArraySettings->push_back(0);
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::ArrayIsEnabled(const char* name)
{
  // Check if there is a specific entry for this array.
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), name);
  if(i != this->ArrayNames->end())
    {
    return (*this->ArraySettings)[i - this->ArrayNames->begin()];
    }

  // The array does not have an entry.  Assume it is disabled.
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::ArrayExists(const char* name)
{
  // Check if there is a specific entry for this array.
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), name);
  return i != this->ArrayNames->end();
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::EnableAllArrays()
{
  int modified = 0;
  for(vtkstd::vector<int>::iterator i = this->ArraySettings->begin();
      i != this->ArraySettings->end(); ++i)
    {
    if(!*i)
      {
      *i = 1;
      modified = 1;
      }
    }
  if(modified)
    {
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::DisableAllArrays()
{
  int modified = 0;
  for(vtkstd::vector<int>::iterator i = this->ArraySettings->begin();
      i != this->ArraySettings->end(); ++i)
    {
    if(*i)
      {
      *i = 0;
      modified = 1;
      }
    }
  if(modified)
    {
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::GetNumberOfArrays()
{
  return static_cast<int>(this->ArrayNames->size());
}

//----------------------------------------------------------------------------
const char* vtkDataArraySelection::GetArrayName(int index)
{
  vtkstd::vector<vtkstd::string>::iterator i = this->ArrayNames->begin()+index;
  if(i >= this->ArrayNames->begin() && i < this->ArrayNames->end())
    {
    return i->c_str();
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::GetArraySetting(int index)
{
  vtkstd::vector<int>::iterator i = this->ArraySettings->begin()+index;
  if(i >= this->ArraySettings->begin() && i < this->ArraySettings->end())
    {
    return *i;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::RemoveAllArrays()
{
  if(this->GetNumberOfArrays() > 0)
    {
    this->ArrayNames->erase(this->ArrayNames->begin(),
                            this->ArrayNames->end());
    this->ArraySettings->erase(this->ArraySettings->begin(),
                               this->ArraySettings->end());
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::AddArray(const char* name)
{
  // This function is called only by the filter owning the selection.
  // It should not call Modified() because array settings are not
  // changed.
  if(this->ArrayExists(name))
    {
    return 0;
    }
  this->ArrayNames->push_back(name);
  this->ArraySettings->push_back(1);
  return 1;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::SetArrays(const char* const* names, int numArrays)
{
  // This function is called only by the filter owning the selection.
  // It should not call Modified() because array settings are not
  // changed.

  // Create a new map for this set of arrays.
  vtkDataArraySelectionArrayNamesType* newNames =
    new vtkDataArraySelectionArrayNamesType;
  vtkDataArraySelectionArraySettingsType* newSettings =
    new vtkDataArraySelectionArraySettingsType;

  newNames->reserve(numArrays);
  newSettings->reserve(numArrays);

  // Fill with settings for all arrays.
  int i;
  for(i=0;i < numArrays; ++i)
    {
    // Add this array.
    newNames->push_back(names[i]);

    // Fill in the setting.  Use the old value if available.
    // Otherwise, default to on.
    vtkstd::vector<vtkstd::string>::iterator it =
      vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(),
                   names[i]);
    int setting = 1;
    if(it != this->ArrayNames->end())
      {
      setting = (*this->ArraySettings)[it - this->ArrayNames->begin()];
      }
    newSettings->push_back(setting);
    }

  // Delete the old map and save the new one.
  delete this->ArrayNames;
  delete this->ArraySettings;
  this->ArrayNames = newNames;
  this->ArraySettings = newSettings;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::CopySelections(vtkDataArraySelection* selections)
{
  if(this == selections)
    {
    return;
    }
  this->RemoveAllArrays();

  this->ArrayNames->insert(this->ArrayNames->begin(),
                           selections->ArrayNames->begin(),
                           selections->ArrayNames->end());
  this->ArraySettings->insert(this->ArraySettings->begin(),
                              selections->ArraySettings->begin(),
                              selections->ArraySettings->end());
  this->Modified();
}
<commit_msg>ENH: fix for irix find and string not const char *<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDataArraySelection.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkDataArraySelection.h"
#include "vtkObjectFactory.h"

#include <vector>
#include <string>
#include <algorithm>

vtkCxxRevisionMacro(vtkDataArraySelection, "1.8");
vtkStandardNewMacro(vtkDataArraySelection);

class vtkDataArraySelectionArrayNamesType: public vtkstd::vector<vtkstd::string> {};
class vtkDataArraySelectionArraySettingsType: public vtkstd::vector<int> {};

//----------------------------------------------------------------------------
vtkDataArraySelection::vtkDataArraySelection()
{
  this->ArrayNames = new vtkDataArraySelectionArrayNamesType;
  this->ArraySettings = new vtkDataArraySelectionArraySettingsType;
}

//----------------------------------------------------------------------------
vtkDataArraySelection::~vtkDataArraySelection()
{
  delete this->ArraySettings;
  delete this->ArrayNames;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Number of Arrays: " << this->GetNumberOfArrays() << "\n";
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::EnableArray(const char* name)
{
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), vtkstd::string(name));
  if(i != this->ArrayNames->end())
    {
    int& setting = (*this->ArraySettings)[i-this->ArrayNames->begin()];
    if(!setting)
      {
      setting = 1;
      this->Modified();
      }
    }
  else
    {
    this->ArrayNames->push_back(name);
    this->ArraySettings->push_back(1);
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::DisableArray(const char* name)
{
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), vtkstd::string(name));
  if(i != this->ArrayNames->end())
    {
    int& setting = (*this->ArraySettings)[i - this->ArrayNames->begin()];
    if(setting)
      {
      setting = 0;
      this->Modified();
      }
    }
  else
    {
    this->ArrayNames->push_back(name);
    this->ArraySettings->push_back(0);
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::ArrayIsEnabled(const char* name)
{
  // Check if there is a specific entry for this array.
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), vtkstd::string(name));
  if(i != this->ArrayNames->end())
    {
    return (*this->ArraySettings)[i - this->ArrayNames->begin()];
    }

  // The array does not have an entry.  Assume it is disabled.
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::ArrayExists(const char* name)
{
  // Check if there is a specific entry for this array.
  vtkstd::vector<vtkstd::string>::iterator i =
    vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(), vtkstd::string(name));
  return i != this->ArrayNames->end();
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::EnableAllArrays()
{
  int modified = 0;
  for(vtkstd::vector<int>::iterator i = this->ArraySettings->begin();
      i != this->ArraySettings->end(); ++i)
    {
    if(!*i)
      {
      *i = 1;
      modified = 1;
      }
    }
  if(modified)
    {
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::DisableAllArrays()
{
  int modified = 0;
  for(vtkstd::vector<int>::iterator i = this->ArraySettings->begin();
      i != this->ArraySettings->end(); ++i)
    {
    if(*i)
      {
      *i = 0;
      modified = 1;
      }
    }
  if(modified)
    {
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::GetNumberOfArrays()
{
  return static_cast<int>(this->ArrayNames->size());
}

//----------------------------------------------------------------------------
const char* vtkDataArraySelection::GetArrayName(int index)
{
  vtkstd::vector<vtkstd::string>::iterator i = this->ArrayNames->begin()+index;
  if(i >= this->ArrayNames->begin() && i < this->ArrayNames->end())
    {
    return i->c_str();
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::GetArraySetting(int index)
{
  vtkstd::vector<int>::iterator i = this->ArraySettings->begin()+index;
  if(i >= this->ArraySettings->begin() && i < this->ArraySettings->end())
    {
    return *i;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::RemoveAllArrays()
{
  if(this->GetNumberOfArrays() > 0)
    {
    this->ArrayNames->erase(this->ArrayNames->begin(),
                            this->ArrayNames->end());
    this->ArraySettings->erase(this->ArraySettings->begin(),
                               this->ArraySettings->end());
    this->Modified();
    }
}

//----------------------------------------------------------------------------
int vtkDataArraySelection::AddArray(const char* name)
{
  // This function is called only by the filter owning the selection.
  // It should not call Modified() because array settings are not
  // changed.
  if(this->ArrayExists(name))
    {
    return 0;
    }
  this->ArrayNames->push_back(name);
  this->ArraySettings->push_back(1);
  return 1;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::SetArrays(const char* const* names, int numArrays)
{
  // This function is called only by the filter owning the selection.
  // It should not call Modified() because array settings are not
  // changed.

  // Create a new map for this set of arrays.
  vtkDataArraySelectionArrayNamesType* newNames =
    new vtkDataArraySelectionArrayNamesType;
  vtkDataArraySelectionArraySettingsType* newSettings =
    new vtkDataArraySelectionArraySettingsType;

  newNames->reserve(numArrays);
  newSettings->reserve(numArrays);

  // Fill with settings for all arrays.
  int i;
  for(i=0;i < numArrays; ++i)
    {
    // Add this array.
    newNames->push_back(names[i]);

    // Fill in the setting.  Use the old value if available.
    // Otherwise, default to on.
    vtkstd::vector<vtkstd::string>::iterator it =
      vtkstd::find(this->ArrayNames->begin(), this->ArrayNames->end(),
                   vtkstd::string(names[i]));
    int setting = 1;
    if(it != this->ArrayNames->end())
      {
      setting = (*this->ArraySettings)[it - this->ArrayNames->begin()];
      }
    newSettings->push_back(setting);
    }

  // Delete the old map and save the new one.
  delete this->ArrayNames;
  delete this->ArraySettings;
  this->ArrayNames = newNames;
  this->ArraySettings = newSettings;
}

//----------------------------------------------------------------------------
void vtkDataArraySelection::CopySelections(vtkDataArraySelection* selections)
{
  if(this == selections)
    {
    return;
    }
  this->RemoveAllArrays();

  this->ArrayNames->insert(this->ArrayNames->begin(),
                           selections->ArrayNames->begin(),
                           selections->ArrayNames->end());
  this->ArraySettings->insert(this->ArraySettings->begin(),
                              selections->ArraySettings->begin(),
                              selections->ArraySettings->end());
  this->Modified();
}
<|endoftext|>


<commit_before>#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsView>
#include <QPainter>
#include <QSettings>
#include <QTextDocument>

#include "TreeNode.hh"
#include "PopupItem.hh"

static const QPointF popupCursorOffset(0, -16);

TreeNode::TreeNode(QGraphicsItem *parent) :
    QGraphicsItem(parent),
    d_active(false),
    d_attributes(),
    d_parentNode(0),
    d_childNodes(),
    d_popupItem(0),
    d_spaceBetweenLayers(40),
    d_spaceBetweenNodes(10),
    d_leafMinimumWidth(30),
    d_leafMinimumHeight(30),
    d_leafPadding(10)
{
    setFlags(ItemIsSelectable | ItemIsFocusable);
    setAcceptHoverEvents(true);
    d_label.setDefaultFont(font());
    d_label.setDocumentMargin(d_leafPadding);
}

bool TreeNode::isLeaf() const
{
    return d_childNodes.length() == 0;
}

void TreeNode::appendChild(TreeNode *child)
{
    child->setParentNode(this);
    d_childNodes.append(child);
}

void TreeNode::setLabel(QString const &label)
{
    d_label.setHtml(label);
}

void TreeNode::setTooltip(QString const &tooltip)
{
    d_tooltip = tooltip;

    if (d_popupItem)
        d_popupItem->setContent(tooltip);
}

QString const &TreeNode::tooltip() const
{
    return d_tooltip;
}

TreeNode *TreeNode::parentNode()
{
    return d_parentNode;
}

void TreeNode::setParentNode(TreeNode *parent)
{
    d_parentNode = parent;
    setParentItem(parent);
}

QList<TreeNode*> TreeNode::children()
{
    return d_childNodes;
}

void TreeNode::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    // This doesn't seem to work well, but is not necessary yet, since
    // we only have popup lines on leaf nodes:
    //
    //QList<QGraphicsItem *> items(scene()->items(event->scenePos(),
    //  Qt::IntersectsItemBoundingRect, Qt::AscendingOrder));
    //if (items.contains(this) && d_popupItem) {
    if (d_popupItem)
    {
        d_popupItem->setPos(event->scenePos());
        d_popupItem->setVisible(true);
        event->accept();
    }
}

void TreeNode::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    if (d_popupItem && d_popupItem->isVisible()) {

        d_popupItem->setVisible(false);
        event->accept();
    }
}

void TreeNode::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    if (d_popupItem && d_popupItem->isVisible()) {
        if (event->screenPos() == event->lastScreenPos())
        {
            d_popupItem->setPos(event->scenePos() + popupCursorOffset / viewScale());
        }
        else
            d_popupItem->setPos(event->scenePos() + popupCursorOffset / viewScale());
        event->accept();
    }
}

void TreeNode::setAttribute(QString const &name, QString const &value)
{
    d_attributes[name] = value;
}

QString TreeNode::asString(QString const &indent) const
{
    QString dump = indent + "[node label: \"" + d_label.toHtml() + "\"";

    dump += "\n" + indent + QString("      attributes: (%1)").arg(d_attributes.size());

    for (QHash<QString, QString>::const_iterator i = d_attributes.constBegin();
        i != d_attributes.constEnd(); ++i)
    {
        dump += " <" + i.key() + ":" + i.value() + ">";
    }

    dump += "\n" + indent + QString("      children: (%1)\n").arg(d_childNodes.length());

    foreach (TreeNode const *child, d_childNodes)
    {
        dump += child->asString(indent + "\t");
    }

    dump += indent + "]\n";

    return dump;
}

QRectF TreeNode::boundingRect() const
{
    /*QRectF branch = branchBoundingRect();
    QRectF leaf = QRectF(QPointF(), leafSize());

    leaf.translate((branch.width() - leaf.width()) / 2, 0);

    return leaf;*/
    return branchBoundingRect();
}

QPainterPath TreeNode::shape() const
{
    QPainterPath path;
    path.addEllipse(leafRect());
    return path;
}

QRectF TreeNode::branchBoundingRect() const
{
    return childrenBoundingRect() | leafBoundingRect();
}

QRectF TreeNode::leafBoundingRect() const
{
    QRectF leaf(leafRect());
    leaf.setWidth(leaf.width() + 10);
    leaf.setHeight(leaf.height() + 10);
    leaf.translate(-5, -5);
    return leaf;
}

QRectF TreeNode::leafRect() const
{
    QSizeF branch(branchSize());
    QRectF leaf(QPointF(0, 0), leafSize());
    leaf.translate(std::max((branch.width() - leaf.width()) / 2, qreal(0)), 0);
    return leaf;
}

QSizeF TreeNode::leafSize() const
{
    return d_label.size();
}

QSizeF TreeNode::branchSize() const
{
    return childrenBoundingRect().size();
}

void TreeNode::layout()
{
    qreal left = 0;
    QSizeF leaf = leafSize();

    if (d_popupItem)
        d_popupItem->setPos(scenePos());

    foreach (TreeNode *child, d_childNodes)
    {
        child->setPos(left, leaf.height() + d_spaceBetweenLayers);
        child->layout();

        left += child->branchBoundingRect().width() + d_spaceBetweenNodes;
    }
}

QFont TreeNode::font() const
{
    return QFont("verdana", 12);
}

void TreeNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QSettings settings;
    settings.beginGroup("Tree");

    QColor activeNodeForeground(settings.value("activeNodeForeground",
        QColor(Qt::white)).value<QColor>());
    QColor activeNodeBackground(settings.value("activeNodeBackground",
        QColor(Qt::darkGreen)).value<QColor>());

    QRectF branch(branchBoundingRect());
    QRectF leaf(leafRect());

    // paint the edges first, so I can paint the leaf right over it
    // which is needed because the edges sometimes leave some anti-alias
    // pixels inside the leaf's box.

    painter->setRenderHint(QPainter::Antialiasing, true);

    paintEdges(painter, leaf);

    painter->setRenderHint(QPainter::Antialiasing, true);

    QColor background = isActive() ? activeNodeBackground : QColor(Qt::white);

    if (isSelected())
        background = background.darker(125);

    painter->fillRect(leaf, background);

    QPen borderPen(Qt::black, hasFocus() ? 3 : 1);
    painter->setPen(borderPen);
    painter->drawRect(leaf);

    paintLabel(painter, leaf);
}

void TreeNode::paintLabel(QPainter *painter, QRectF const &leaf)
{
    // Necessary for centred text.
    d_label.setTextWidth(leaf.width());

    painter->save();
    painter->translate(leaf.topLeft());
    d_label.drawContents(painter, QRectF(QPointF(0,0), leaf.size()));
    painter->restore();
}

void TreeNode::paintEdges(QPainter *painter, QRectF const &leaf)
{
    QPen edgePen(Qt::black, 1);
    painter->setPen(edgePen);

    QPointF origin(leaf.x() + leaf.width() / 2, leaf.y() + leaf.height());

    foreach (TreeNode const *child, d_childNodes)
    {
        // child's top center position, where the leaf should be found
        QPointF target(child->pos() + QPointF(child->branchBoundingRect().width() / 2, 0));

        painter->drawLine(origin, target);
    }
}

qreal TreeNode::viewScale() const
{
    if (!scene() || scene()->views().isEmpty())
        return 1.0;

    return scene()->views().first()->transform().m11();
}
<commit_msg>Experiment with different ways to indicate matching nodes in tree.<commit_after>#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsView>
#include <QPainter>
#include <QSettings>
#include <QTextDocument>

#include "TreeNode.hh"
#include "PopupItem.hh"

static const QPointF popupCursorOffset(0, -16);

TreeNode::TreeNode(QGraphicsItem *parent) :
    QGraphicsItem(parent),
    d_active(false),
    d_attributes(),
    d_parentNode(0),
    d_childNodes(),
    d_popupItem(0),
    d_spaceBetweenLayers(40),
    d_spaceBetweenNodes(10),
    d_leafMinimumWidth(30),
    d_leafMinimumHeight(30),
    d_leafPadding(10)
{
    setFlags(ItemIsSelectable | ItemIsFocusable);
    setAcceptHoverEvents(true);
    d_label.setDefaultFont(font());
    d_label.setDocumentMargin(d_leafPadding);
}

bool TreeNode::isLeaf() const
{
    return d_childNodes.length() == 0;
}

void TreeNode::appendChild(TreeNode *child)
{
    child->setParentNode(this);
    d_childNodes.append(child);
}

void TreeNode::setLabel(QString const &label)
{
    d_label.setHtml(label);
}

void TreeNode::setTooltip(QString const &tooltip)
{
    d_tooltip = tooltip;

    if (d_popupItem)
        d_popupItem->setContent(tooltip);
}

QString const &TreeNode::tooltip() const
{
    return d_tooltip;
}

TreeNode *TreeNode::parentNode()
{
    return d_parentNode;
}

void TreeNode::setParentNode(TreeNode *parent)
{
    d_parentNode = parent;
    setParentItem(parent);
}

QList<TreeNode*> TreeNode::children()
{
    return d_childNodes;
}

void TreeNode::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    // This doesn't seem to work well, but is not necessary yet, since
    // we only have popup lines on leaf nodes:
    //
    //QList<QGraphicsItem *> items(scene()->items(event->scenePos(),
    //  Qt::IntersectsItemBoundingRect, Qt::AscendingOrder));
    //if (items.contains(this) && d_popupItem) {
    if (d_popupItem)
    {
        d_popupItem->setPos(event->scenePos());
        d_popupItem->setVisible(true);
        event->accept();
    }
}

void TreeNode::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    if (d_popupItem && d_popupItem->isVisible()) {

        d_popupItem->setVisible(false);
        event->accept();
    }
}

void TreeNode::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    if (d_popupItem && d_popupItem->isVisible()) {
        if (event->screenPos() == event->lastScreenPos())
        {
            d_popupItem->setPos(event->scenePos() + popupCursorOffset / viewScale());
        }
        else
            d_popupItem->setPos(event->scenePos() + popupCursorOffset / viewScale());
        event->accept();
    }
}

void TreeNode::setAttribute(QString const &name, QString const &value)
{
    d_attributes[name] = value;
}

QString TreeNode::asString(QString const &indent) const
{
    QString dump = indent + "[node label: \"" + d_label.toHtml() + "\"";

    dump += "\n" + indent + QString("      attributes: (%1)").arg(d_attributes.size());

    for (QHash<QString, QString>::const_iterator i = d_attributes.constBegin();
        i != d_attributes.constEnd(); ++i)
    {
        dump += " <" + i.key() + ":" + i.value() + ">";
    }

    dump += "\n" + indent + QString("      children: (%1)\n").arg(d_childNodes.length());

    foreach (TreeNode const *child, d_childNodes)
    {
        dump += child->asString(indent + "\t");
    }

    dump += indent + "]\n";

    return dump;
}

QRectF TreeNode::boundingRect() const
{
    /*QRectF branch = branchBoundingRect();
    QRectF leaf = QRectF(QPointF(), leafSize());

    leaf.translate((branch.width() - leaf.width()) / 2, 0);

    return leaf;*/
    return branchBoundingRect();
}

QPainterPath TreeNode::shape() const
{
    QPainterPath path;
    path.addEllipse(leafRect());
    return path;
}

QRectF TreeNode::branchBoundingRect() const
{
    return childrenBoundingRect() | leafBoundingRect();
}

QRectF TreeNode::leafBoundingRect() const
{
    QRectF leaf(leafRect());
    leaf.setWidth(leaf.width() + 10);
    leaf.setHeight(leaf.height() + 10);
    leaf.translate(-5, -5);
    return leaf;
}

QRectF TreeNode::leafRect() const
{
    QSizeF branch(branchSize());
    QRectF leaf(QPointF(0, 0), leafSize());
    leaf.translate(std::max((branch.width() - leaf.width()) / 2, qreal(0)), 0);
    return leaf;
}

QSizeF TreeNode::leafSize() const
{
    return d_label.size();
}

QSizeF TreeNode::branchSize() const
{
    return childrenBoundingRect().size();
}

void TreeNode::layout()
{
    qreal left = 0;
    QSizeF leaf = leafSize();

    if (d_popupItem)
        d_popupItem->setPos(scenePos());

    foreach (TreeNode *child, d_childNodes)
    {
        child->setPos(left, leaf.height() + d_spaceBetweenLayers);
        child->layout();

        left += child->branchBoundingRect().width() + d_spaceBetweenNodes;
    }
}

QFont TreeNode::font() const
{
    return QFont("verdana", 12);
}

void TreeNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QSettings settings;
    settings.beginGroup("Tree");

    QColor activeNodeForeground(settings.value("activeNodeForeground",
        QColor(Qt::white)).value<QColor>());
    QColor activeNodeBackground(settings.value("activeNodeBackground",
        QColor(Qt::darkGreen)).value<QColor>());

    QRectF branch(branchBoundingRect());
    QRectF leaf(leafRect());

    // paint the edges first, so I can paint the leaf right over it
    // which is needed because the edges sometimes leave some anti-alias
    // pixels inside the leaf's box.

    painter->setRenderHint(QPainter::Antialiasing, true);

    paintEdges(painter, leaf);

    painter->setRenderHint(QPainter::Antialiasing, true);

    QColor background(Qt::white);

    if (isSelected())
        background = background.darker(125);

    QPen borderPen(isActive() ? activeNodeBackground : QColor(Qt::black), isActive() ? 3 : 1);

    if (!isSelected() && !isActive())
        borderPen.setStyle(Qt::DashLine);

    painter->fillRect(leaf, background);
    painter->setPen(borderPen);
    painter->drawRect(leaf);

    paintLabel(painter, leaf);
}

void TreeNode::paintLabel(QPainter *painter, QRectF const &leaf)
{
    // Necessary for centred text.
    d_label.setTextWidth(leaf.width());

    painter->save();
    painter->translate(leaf.topLeft());
    d_label.drawContents(painter, QRectF(QPointF(0,0), leaf.size()));
    painter->restore();
}

void TreeNode::paintEdges(QPainter *painter, QRectF const &leaf)
{
    QPen edgePen(Qt::black, 1);
    painter->setPen(edgePen);

    QPointF origin(leaf.x() + leaf.width() / 2, leaf.y() + leaf.height());

    foreach (TreeNode const *child, d_childNodes)
    {
        // child's top center position, where the leaf should be found
        QPointF target(child->pos() + QPointF(child->branchBoundingRect().width() / 2, 0));

        painter->drawLine(origin, target);
    }
}

qreal TreeNode::viewScale() const
{
    if (!scene() || scene()->views().isEmpty())
        return 1.0;

    return scene()->views().first()->transform().m11();
}
<|endoftext|>


<commit_before>#include "mitkParRecFileReader.h"
#include <itkImageFileReader.h>

#ifdef __GNUC__
#define stricmp strcasecmp
#endif

void mitk::ParRecFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  m_RecFileName = "";
  if( m_FileName != "")
  {
    int extPos=m_FileName.find_last_of(".");
    if(extPos>=-1)
    {
      const char *ext=m_FileName.c_str()+extPos+1;
      if(stricmp(ext,"par")==0)
        m_RecFileName = m_FileName.substr(0,extPos);
      else
        m_RecFileName = m_FileName;
    }
    else
        m_RecFileName = m_FileName;

    m_RecFileName.append(".rec");

    bool headerRead = false;

    mitk::PixelType type;
    unsigned int dimension=0;
    unsigned int dimensions[4]={0,0,1,1};
    float sliceThickness=0.0;
    float sliceGap=0.0;
    float sliceSpacing=0.0;
    mitk::Vector3D thickness(1.0,1.0,1.0);
    mitk::Vector3D gap(0.0,0.0,0.0);
    mitk::Vector3D spacing;

    FILE *f;
    f=fopen(m_FileName.c_str(), "r");
    if(f!=NULL)
    {
      while(!feof(f))
      {
        char s[300], *p;
        fgets(s,200,f);
        if(strstr(s,"Max. number of cardiac phases"))
        {
          p=strchr(s,':')+1;
          dimensions[3]=atoi(p);
          if(dimensions[3]>1)
            dimension=4;
        }
        else
        if(strstr(s,"Max. number of slices/locations"))
        {
          p=strchr(s,':')+1;
          dimensions[2]=atoi(p);
          if(dimension==0)
          {
            if(dimensions[2]>1)
              dimension=3;
            else
              dimension=2;
          }
        }
        else
        if(strstr(s,"Image pixel size"))
        {
          p=strchr(s,':')+1;
          int bpe=atoi(p);
          if(bpe==8)
            type=typeid(ipUInt1_t);
          else
            type=typeid(ipUInt2_t);
        }
        else
        if(strstr(s,"Recon resolution"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%u %u", dimensions, dimensions+1);
        }
        else
        if(strstr(s,"FOV (ap,fh,rl) [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f %f %f", &thickness.x, &thickness.y, &thickness.z);
        }
        else
        if(strstr(s,"Slice thickness [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f", &sliceThickness);
        }
        else
        if(strstr(s,"Slice gap [mm]"))
        {
          p=s+strcspn(s,"-0123456789");
          sscanf(p,"%f", &sliceGap);
        }
      }
      fclose(f);

//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
      sliceSpacing = sliceThickness+sliceGap;
      if(fabs(thickness.x/dimensions[2]-sliceSpacing)<0.0001)
        thickness.x=thickness.y;
      else
      if(fabs(thickness.y/dimensions[2]-sliceSpacing)<0.0001)
        thickness.y=thickness.x;
      thickness.z=sliceSpacing;

      thickness.x/=dimensions[0];
      thickness.y/=dimensions[1];
      spacing=thickness+gap;

      if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0))
        headerRead = true;
    }

    if( headerRead == false)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << m_FileName.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(type, dimension, dimensions);
    output->GetSlicedGeometry()->SetSpacing(spacing);

    output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
    output->GetSlicedGeometry()->SetEvenlySpaced();
  }

  m_ReadHeaderTime.Modified();
}

void mitk::ParRecFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_RecFileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
  }

  if( m_RecFileName != "")
  {
    FILE *f = fopen(m_RecFileName.c_str(), "r");
    if(f==NULL)
    {
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
    }

    int z, zmax;
    int t, tmax;

    z=output->GetRequestedRegion().GetIndex(2);
    t=output->GetRequestedRegion().GetIndex(3);

    zmax=z+output->GetRequestedRegion().GetSize(2);
    tmax=t+output->GetRequestedRegion().GetSize(3);

    int sliceSize=output->GetDimension(0)*output->GetDimension(1)*output->GetPixelType().GetBpe()/8;
    void *data = malloc(sliceSize);

    bool ignore4Dtopogram=false;
    {
      int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
    if(output->GetDimension(3)>1)
      ignore4Dtopogram=true;

      for(;t<tmax;++t)
        for(;z<zmax;++z)
        {
			    if(ignore4Dtopogram)
            fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
          else
            fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
      	  fread(data, sliceSize, 1, f);
          output->SetSlice(data,z,t,0);
        }
    }
    //else
    //{
    //  for(;z<zmax;++z)
    //  {
    //    fseek(f,sliceSize*z,SEEK_SET);
    //  	fread(data, sliceSize, 1, f);
    //    output->SetSlice(data,z,0,0);
    //  }
    //}
    free(data);
  }
}

mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

mitk::ParRecFileReader::~ParRecFileReader()
{
}
<commit_msg>fixed usage of requested-region<commit_after>#include "mitkParRecFileReader.h"
#include <itkImageFileReader.h>

#ifdef __GNUC__
#define stricmp strcasecmp
#endif

void mitk::ParRecFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  m_RecFileName = "";
  if( m_FileName != "")
  {
    int extPos=m_FileName.find_last_of(".");
    if(extPos>=-1)
    {
      const char *ext=m_FileName.c_str()+extPos+1;
      if(stricmp(ext,"par")==0)
        m_RecFileName = m_FileName.substr(0,extPos);
      else
        m_RecFileName = m_FileName;
    }
    else
        m_RecFileName = m_FileName;

    m_RecFileName.append(".rec");

    bool headerRead = false;

    mitk::PixelType type;
    unsigned int dimension=0;
    unsigned int dimensions[4]={0,0,1,1};
    float sliceThickness=0.0;
    float sliceGap=0.0;
    float sliceSpacing=0.0;
    mitk::Vector3D thickness(1.0,1.0,1.0);
    mitk::Vector3D gap(0.0,0.0,0.0);
    mitk::Vector3D spacing;

    FILE *f;
    f=fopen(m_FileName.c_str(), "r");
    if(f!=NULL)
    {
      while(!feof(f))
      {
        char s[300], *p;
        fgets(s,200,f);
        if(strstr(s,"Max. number of cardiac phases"))
        {
          p=strchr(s,':')+1;
          dimensions[3]=atoi(p);
          if(dimensions[3]>1)
            dimension=4;
        }
        else
        if(strstr(s,"Max. number of slices/locations"))
        {
          p=strchr(s,':')+1;
          dimensions[2]=atoi(p);
          if(dimension==0)
          {
            if(dimensions[2]>1)
              dimension=3;
            else
              dimension=2;
          }
        }
        else
        if(strstr(s,"Image pixel size"))
        {
          p=strchr(s,':')+1;
          int bpe=atoi(p);
          if(bpe==8)
            type=typeid(ipUInt1_t);
          else
            type=typeid(ipUInt2_t);
        }
        else
        if(strstr(s,"Recon resolution"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%u %u", dimensions, dimensions+1);
        }
        else
        if(strstr(s,"FOV (ap,fh,rl) [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f %f %f", &thickness.x, &thickness.y, &thickness.z);
        }
        else
        if(strstr(s,"Slice thickness [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f", &sliceThickness);
        }
        else
        if(strstr(s,"Slice gap [mm]"))
        {
          p=s+strcspn(s,"-0123456789");
          sscanf(p,"%f", &sliceGap);
        }
      }
      fclose(f);

//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
      sliceSpacing = sliceThickness+sliceGap;
      if(fabs(thickness.x/dimensions[2]-sliceSpacing)<0.0001)
        thickness.x=thickness.y;
      else
      if(fabs(thickness.y/dimensions[2]-sliceSpacing)<0.0001)
        thickness.y=thickness.x;
      thickness.z=sliceSpacing;

      thickness.x/=dimensions[0];
      thickness.y/=dimensions[1];
      spacing=thickness+gap;

      if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0))
        headerRead = true;
    }

    if( headerRead == false)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << m_FileName.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(type, dimension, dimensions);
    output->GetSlicedGeometry()->SetSpacing(spacing);

    output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
    output->GetSlicedGeometry()->SetEvenlySpaced();
  }

  m_ReadHeaderTime.Modified();
}

void mitk::ParRecFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_RecFileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
  }

  if( m_RecFileName != "")
  {
    FILE *f = fopen(m_RecFileName.c_str(), "r");
    if(f==NULL)
    {
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
    }

    int zstart, zmax;
    int tstart, tmax;

    zstart=output->GetRequestedRegion().GetIndex(2);
    tstart=output->GetRequestedRegion().GetIndex(3);

    zmax=zstart+output->GetRequestedRegion().GetSize(2);
    tmax=tstart+output->GetRequestedRegion().GetSize(3);

    bool ignore4Dtopogram=false;
    {
      int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
    if(output->GetDimension(3)>1)
      ignore4Dtopogram=true;

      int z,t;
      for(t=tstart;t<tmax;++t)
        for(z=zstart;z<zmax;++z)
        {
			    if(ignore4Dtopogram)
            fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
          else
            fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
      	  fread(data, sliceSize, 1, f);
          output->SetSlice(data,z,t,0);
        }
    }
    //else
    //{
    //  for(;z<zmax;++z)
    //  {
    //    fseek(f,sliceSize*z,SEEK_SET);
    //  	fread(data, sliceSize, 1, f);
    //    output->SetSlice(data,z,0,0);
    //  }
    //}
    free(data);
  }
}

mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

mitk::ParRecFileReader::~ParRecFileReader()
{
}
<|endoftext|>