<commit_before>#include "Ising.h"
#include "Utilities.h"

#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z & 1);
    }

    int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.getTau())>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.getTau());

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    for (int k = 0; k<clusters; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);
    char &currentCell = getCell(currentCoord);
    unsigned char clusterBit = currentCell;
    currentCell^=1;

    double inclusionProbability = 1 - exp(-2*constants.getBeta());
    assert(inclusionProbability<=1 && inclusionProbability>=0);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (neighborCell == clusterBit &&
                    gsl_rng_uniform(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
                neighborCell^=1;
            }
        }
        assert(workStack.size()<SQUARED((unsigned)isingSide));
    };

}

void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);
    char s3 = parity;
    int inputState = s(s1, s2, s3);

    CheckTransitionRuleError(inputState<8 && inputState>=0,
                             InvalidInputStateError);

    SystemState *lastState = currentState;

    CheckTransitionRuleError(transitions.count(currentState),
                             EmptyTransitionRuleError);

    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    CheckTransitionRuleError(currentTable.size() == 8 &&
                                "Transition table size should be 8",
                             InvalidTableSizeError);
    CheckTransitionRuleError(nextState && "nextState must not be null.",
                             TransitionDeadEndError);

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - (s1 ^ s2);

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - (s1 ^ s2);

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants,
                               int IS, int cls, TransitionRule rule) :
        Reservoir(constants), isingSide(IS), RNG(RNG_), clusters(cls) {
    transitions = rule;
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
    currentState = randomState();
}

TransitionRule defaultTransitionRule() {
    //Source: http://imgur.com/FF5TBQh

    TransitionRule transitions;

    #define TTable(XX) \
        TransitionTable XX;\
        for (char k=0; k<8; k++) \
            XX[k]=&State##XX;

    TTable(A1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    TTable(B1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    TTable(C1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    TTable(A0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    TTable(B0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    TTable(C0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;

    return transitions;
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension,clusters);
}

void isingEnergyDistribution(int d, int clusters) {
    double delta = .5;
    double tau = 1;
    double epsilon = 0;
    Constants constants(delta,epsilon,tau);

    gsl_rng *RNG = GSLRandomNumberGenerator();
    for (int energy = 0; energy!=4; energy++) {
        constants.setEpsilon(.15*energy+.25);
        printf("Beta: %lf\n",constants.getBeta());
        IsingReservoir *reservoir = new IsingReservoir(RNG,constants,d,clusters);
        reservoir->reset();
        for (int k=0; k<100; k++) {
            printf("%d\n",reservoir->totalEnergy());
            reservoir->reset();
        }
        delete reservoir;
        printf("\n");
    }
}

int IsingReservoir::totalEnergy() {
    int N = SQUARED(isingSide);
    int energy = 0;
    for (int k = 0; k<N; k++) {
        int row = (int)(k % this->isingSide);
        int column = (int)(k / this->isingSide);
        energy += getEnergy(Coordinate(row, column));
    }
    // This method overcounts by two, considering both the forward and
    // backword bonds.
    return energy/2;
}
<commit_msg>Initialize parity bit.<commit_after>#include "Ising.h"
#include "Utilities.h"

#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z & 1);
    }

    int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.getTau())>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.getTau());

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    for (int k = 0; k<clusters; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);
    char &currentCell = getCell(currentCoord);
    unsigned char clusterBit = currentCell;
    currentCell^=1;

    double inclusionProbability = 1 - exp(-2*constants.getBeta());
    assert(inclusionProbability<=1 && inclusionProbability>=0);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (neighborCell == clusterBit &&
                    gsl_rng_uniform(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
                neighborCell^=1;
            }
        }
        assert(workStack.size()<SQUARED((unsigned)isingSide));
    };

}

void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);
    char s3 = parity;
    int inputState = s(s1, s2, s3);

    CheckTransitionRuleError(inputState<8 && inputState>=0,
                             InvalidInputStateError);

    SystemState *lastState = currentState;

    CheckTransitionRuleError(transitions.count(currentState),
                             EmptyTransitionRuleError);

    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    CheckTransitionRuleError(currentTable.size() == 8 &&
                                "Transition table size should be 8",
                             InvalidTableSizeError);
    CheckTransitionRuleError(nextState && "nextState must not be null.",
                             TransitionDeadEndError);

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - (s1 ^ s2);

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - (s1 ^ s2);

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants,
                               int IS, int cls, TransitionRule rule) :
        Reservoir(constants), isingSide(IS), RNG(RNG_), clusters(cls) {
    parity = 0;
    transitions = rule;
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
    currentState = randomState();
}

TransitionRule defaultTransitionRule() {
    //Source: http://imgur.com/FF5TBQh

    TransitionRule transitions;

    #define TTable(XX) \
        TransitionTable XX;\
        for (char k=0; k<8; k++) \
            XX[k]=&State##XX;

    TTable(A1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    TTable(B1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    TTable(C1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    TTable(A0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    TTable(B0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    TTable(C0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;

    return transitions;
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension,clusters);
}

void isingEnergyDistribution(int d, int clusters) {
    double delta = .5;
    double tau = 1;
    double epsilon = 0;
    Constants constants(delta,epsilon,tau);

    gsl_rng *RNG = GSLRandomNumberGenerator();
    for (int energy = 0; energy!=4; energy++) {
        constants.setEpsilon(.15*energy+.25);
        printf("Beta: %lf\n",constants.getBeta());
        IsingReservoir *reservoir = new IsingReservoir(RNG,constants,d,clusters);
        reservoir->reset();
        for (int k=0; k<100; k++) {
            printf("%d\n",reservoir->totalEnergy());
            reservoir->reset();
        }
        delete reservoir;
        printf("\n");
    }
}

int IsingReservoir::totalEnergy() {
    int N = SQUARED(isingSide);
    int energy = 0;
    for (int k = 0; k<N; k++) {
        int row = (int)(k % this->isingSide);
        int column = (int)(k / this->isingSide);
        energy += getEnergy(Coordinate(row, column));
    }
    // This method overcounts by two, considering both the forward and
    // backword bonds.
    return energy/2;
}
<|endoftext|>


<commit_before>#include "Ising.h"
#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    inline int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z);
    }

    inline int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.tau)>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.tau);

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

inline void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    currentState = randomState();
    for (int k = 0; k<2000; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (currentCell!=neighborCell) {
                continue;
            }

            double inclusionProbability = 1 - exp(-2*constants.beta());
            if (gsl_rng_get(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
            }
        }

        // Once the current cell has been flipped, we don't need
        // to worry about keeping track of considered bonds.
        currentCell = (currentCell + 1) % 2;
    }

}

inline void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);

    int inputState = s(s1,s2,parity % 2);

    SystemState *lastState = currentState;
    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    assert(inputState<8 && inputState>=0 && "Invalid input state.");
    assert(currentTable.size() == 8 && "Transition table size should be 8");
    assert(nextState && "nextState must not be null.");

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

inline int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

inline int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

inline char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

inline int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants, int IS) : Reservoir(constants), isingSide(IS), RNG(RNG_) {
    setupStateTable();
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
}

inline void IsingReservoir::setupStateTable() {
    //TODO: Custom states. This is goofy.
    //Source: http://imgur.com/FF5TBQh

    #define init(XX,StateXX) \
                TransitionTable XX;\
                for (char k=0; k<8; k++) \
                    XX[k]=&StateXX;
    init(A1,StateA1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    init(B1,StateB1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    init(C1,StateC1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    init(A0,StateA0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    init(B0,StateB0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    init(C0,StateC0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;
    //TODO: TEST ME.
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension);
}
<commit_msg>Use a more reasonable number of ising iterations.<commit_after>#include "Ising.h"
#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    inline int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z);
    }

    inline int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.tau)>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.tau);

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

inline void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    currentState = randomState();
    for (int k = 0; k<200; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (currentCell!=neighborCell) {
                continue;
            }

            double inclusionProbability = 1 - exp(-2*constants.beta());
            if (gsl_rng_get(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
            }
        }

        // Once the current cell has been flipped, we don't need
        // to worry about keeping track of considered bonds.
        currentCell = (currentCell + 1) % 2;
    }

}

inline void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);

    int inputState = s(s1,s2,parity % 2);

    SystemState *lastState = currentState;
    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    assert(inputState<8 && inputState>=0 && "Invalid input state.");
    assert(currentTable.size() == 8 && "Transition table size should be 8");
    assert(nextState && "nextState must not be null.");

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

inline int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

inline int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

inline char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

inline int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants, int IS) : Reservoir(constants), isingSide(IS), RNG(RNG_) {
    setupStateTable();
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
}

inline void IsingReservoir::setupStateTable() {
    //TODO: Custom states. This is goofy.
    //Source: http://imgur.com/FF5TBQh

    #define init(XX,StateXX) \
                TransitionTable XX;\
                for (char k=0; k<8; k++) \
                    XX[k]=&StateXX;
    init(A1,StateA1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    init(B1,StateB1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    init(C1,StateC1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    init(A0,StateA0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    init(B0,StateB0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    init(C0,StateC0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;
    //TODO: TEST ME.
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension);
}
<|endoftext|>


<commit_before>#include <assert.h>

#include "global.h"

#include "Level.h"
#include "blocks.h"
#include "2d/cube.h"

void begin_compound(void *context, nbt::String name) {
  if (name.compare("Level") == 0) {
    ((Level*)context)->islevel = true;
  }
}

void register_int(void *context, nbt::String name, nbt::Int i) {
  Level *level = ((Level*)context);

  if (!level->islevel) {
    return;
  }

  if (name.compare("xPos") == 0) {
    level->xPos = i;
    return;
  }

  if (name.compare("zPos") == 0) {
    level->zPos = i;
    return;
  }
}

void register_byte_array(void *context, nbt::String name, nbt::ByteArray* byte_array) {
  Level *level = ((Level*)context);

  if (!level->islevel) {
    delete byte_array;
    return;
  }

  if (name.compare("Blocks") == 0) {
    level->blocks = byte_array;
    return;
  }

  if (name.compare("SkyLight") == 0) {
    level->skylight = byte_array;
    return;
  }

  if (name.compare("HeightMap") == 0) {
    level->heightmap = byte_array;
    return;
  }

  if (name.compare("BlockLight") == 0) {
    level->blocklight = byte_array;
    return;
  }
}

void error_handler(void *context, size_t where, const char *why) {
  Level *level = ((Level *)context);
  level->grammar_error = true;
  level->grammar_error_where = where;
  level->grammar_error_why = why;
}

#include <iostream>

Level::~Level(){
  if (ignore_blocks) {
    return;
  }

  std::cout << "Deallocating blocks..." << std::endl;

  if (blocks != NULL) delete blocks;
  if (skylight != NULL) delete skylight;
  if (heightmap != NULL) delete heightmap;
  if (blocklight != NULL) delete blocklight;
}

Level::Level(const char *path, bool ignore_blocks)
  : path(path), ignore_blocks(ignore_blocks)
{
  xPos = 0;
  zPos = 0;
  islevel = false;
  grammar_error = false;

  nbt::Parser parser(this);

  if (!ignore_blocks) {
    parser.register_byte_array = register_byte_array;
  }

  parser.register_int = register_int;
  parser.begin_compound = begin_compound;
  parser.error_handler = error_handler;

  try {
    parser.parse_file(path);
  } catch(nbt::bad_grammar &bg) {
    grammar_error = true;
  }
}

/**
 * Blocks[ z + ( y * ChunkSizeY(=128) + ( x * ChunkSizeY(=128) * ChunkSizeZ(=16) ) ) ];
 */
nbt::Byte bget(nbt::ByteArray *blocks, int x, int z, int y) {
  assert(x >= 0 && x < mc::MapX);
  assert(z >= 0 && z < mc::MapZ);
  assert(y >= 0 && y < mc::MapY);
  int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
  assert (p >= 0 && p < blocks->length);
  return blocks->values[p];
}

nbt::Byte bsget(nbt::ByteArray *skylight, int x, int z, int y) {
  assert(x >= 0 && x < mc::MapX);
  assert(z >= 0 && z < mc::MapZ);
  assert(y >= 0 && y < mc::MapY);
  int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
  int ap = p / 2;

  assert (ap >= 0 && ap < skylight->length);

  // force unsigned
  uint8_t bp = skylight->values[ap] & 0xff;

  if (p % 2 == 0) {
    return bp >> 4;
  }
  else {
    return bp & 0xf;
  }
}

void transform_xz(settings_t& s, int &x, int &z) {
  /*if (s->flip) {
    int t = x;
    x = z;
    z = mc::MapZ - t - 1;
  }

  if (s->invert) {
    z = mc::MapZ - z - 1;
    x = mc::MapX - x - 1;
  }*/
}

inline void apply_shading(settings_t& s, int bl, int sl, int hm, int y, Color &c) {
  // if night, darken all colors not emitting light
  if (s.night) {
    c.darken((0xd0 * (16 - bl)) / 16);
  }

  c.darken((mc::MapY - y));
}

inline bool cavemode_isopen(int bt) {
  switch(bt) {
    case mc::Air: return true;
    case mc::Leaves: return true;
    default: return false;
  }
}

inline bool cavemode_ignore_block(settings_t& s, int x, int z, int y, int bt, nbt::ByteArray *blocks, bool &cave_initial) {
  if (cave_initial) {
    if (!cavemode_isopen(bt)) {
      cave_initial = false;
      return true;
    }

    return true;
  }

  if (!cavemode_isopen(bt)) {
    if (y < s.top && cavemode_isopen(bget(blocks, x, z, y + 1))) {
      return false;
    }
  }

  return true;
}

class BlockRotation {
private:
  settings_t& s;
  nbt::ByteArray *byte_array;

  void transform_xz(int& x, int& z) {
    switch (s.rotation) {
      case 270:
        z = mc::MapZ - z - 1;
        x = mc::MapX - x - 1;
        {
          int t = x;
          x = z;
          z = mc::MapZ - t - 1;
        }
        break;
      case 180:
        z = mc::MapZ - z - 1;
        x = mc::MapX - x - 1;
        break;
      case 90:
        {
          int t = x;
          x = z;
          z = mc::MapZ - t - 1;
        }
        break;
    };
  }

public:
  BlockRotation(settings_t& s, nbt::ByteArray *byte_array)
    : s(s), byte_array(byte_array) {}

  uint8_t get8(int x, int z, int y) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    assert(y >= 0 && y < mc::MapY);
    int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
    assert (p >= 0 && p < byte_array->length);
    return byte_array->values[p];
  }

  uint8_t get8(int x, int z) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    int p = x + (z * mc::MapX);
    assert (p >= 0 && p < byte_array->length);
    return byte_array->values[p];
  }

  uint8_t get4(int x, int z, int y) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    assert(y >= 0 && y < mc::MapY);
    int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
    int ap = p / 2;

    assert (ap >= 0 && ap < byte_array->length);

    // force unsigned
    uint8_t bp = byte_array->values[ap] & 0xff;

    if (p % 2 == 0) {
      return bp >> 4;
    }
    else {
      return bp & 0xf;
    }
  }
};

ImageBuffer *Level::get_image(settings_t& s) {
  ImageBuffer *img = new ImageBuffer(mc::MapX, mc::MapZ, 1);

  if (!islevel) {
    return img;
  }

  img->set_reversed(true);

  // block type
  int bt;

  for (int x = 0, mz = mc::MapZ - 1; x < mc::MapX; x++, mz--) {
    for (int y = 0, mx = 0; y < mc::MapX; y++, mx++) {
      Color base(255, 255, 255, 0);

      bt = mc::Air;

      bool cave_initial = true;

      int my;

      BlockRotation blocks_r(s, blocks);
      BlockRotation blocklight_r(s, blocklight);
      BlockRotation skylight_r(s, skylight);

      // do incremental color fill until color is opaque
      for (my = s.top; my > s.bottom; my--) {
        bt = blocks_r.get8(mx, mz, my);

        if (s.cavemode && cavemode_ignore_block(s, mx, mz, my, bt, blocks, cave_initial)) {
          continue;
        }

        if (s.excludes[bt]) {
          continue;
        }

        Color bc(mc::MaterialColor[bt]);

        int bl = blocklight_r.get4(mx, mz, my),
            sl = skylight_r.get4(mx, mz, my);

        apply_shading(s, bl, sl, 0, my, bc);

        base.underlay(bc);

        if (base.is_opaque()) {
          break;
        }
      }

      if (base.is_transparent()) {
        continue;
      }

      img->set_pixel(x, y, 0, base);
    }
  }

  return img;
}

ImageBuffer *Level::get_oblique_image(settings_t& s)
{
  ImageBuffer *img = new ImageBuffer(mc::MapX, mc::MapZ + mc::MapY, mc::MapY + mc::MapZ);

  if (!islevel) {
    return img;
  }

  Cube c(mc::MapX, mc::MapY, mc::MapZ);

  // block type
  int bt;

  BlockRotation blocks_r(s, blocks);
  BlockRotation blocklight_r(s, blocklight);
  BlockRotation skylight_r(s, skylight);

  for (int x = 0, mz = mc::MapZ - 1; x < mc::MapX; x++, mz--) {
    for (int y = 0, mx = 0; y < mc::MapX; y++, mx++) {
      bool cave_initial = true;
      int cavemode_top = s.top;

      if (s.cavemode) {
        for (int my = s.top; my > 0; my--) {
          bt = blocks_r.get8(mx, mz, y);

          if (!cavemode_isopen(bt)) {
            cavemode_top = my;
            break;
          }
        }
      }

      for (int my = s.bottom; my < s.top; my++) {
        point p(x, my, y);

        bt = blocks_r.get8(mx, mz, my);

        if (s.cavemode) {
          if (cavemode_ignore_block(s, mx, mz, my, bt, blocks, cave_initial) || my >= cavemode_top) {
            continue;
          }
        }

        if (s.excludes[bt]) {
          continue;
        }

        int bl = blocklight_r.get4(mx, mz, my),
            sl = skylight_r.get4(mx, mz, my);

        int px, py;
        c.project_oblique(p, px, py);

        Color top(mc::MaterialColor[bt]);
        apply_shading(s, bl, sl, 0, my, top);
        img->add_pixel(px, py - 1, top);

        Color side(mc::MaterialSideColor[bt]);
        apply_shading(s, bl, sl, 0, my, side);
        img->add_pixel(px, py, side);
      }
    }
  }

  return img;
}

ImageBuffer *Level::get_obliqueangle_image(settings_t& s)
{
  ImageBuffer *img = new ImageBuffer(mc::MapX * 2 + 1, mc::MapX + mc::MapY + mc::MapZ, mc::MapY + mc::MapZ * 2);

  if (!islevel) {
    return img;
  }

  Cube c(mc::MapX, mc::MapY, mc::MapZ);

  // block type
  int bt;

  BlockRotation blocks_r(s, blocks);
  BlockRotation blocklight_r(s, blocklight);
  BlockRotation skylight_r(s, skylight);
  BlockRotation heightmap_r(s, heightmap);

  for (int z = 0; z < c.z; z++) {
    for (int x = 0; x < c.x; x++) {
      bool cave_initial = true;

      int cavemode_top = s.top;

      if (s.cavemode) {
        for (int y = s.top; y > 0; y--) {
          bt = blocks_r.get8(x, z, y);

          if (!cavemode_isopen(bt)) {
            cavemode_top = y;
            break;
          }
        }
      }

      int hmval = heightmap_r.get8(x, z);

      for (int y = s.bottom; y < s.top; y++) {
        point p(x, y, z);

        bt = blocks_r.get8(x, z, y);

        if (s.cavemode) {
          if (cavemode_ignore_block(s, x, z, y, bt, blocks, cave_initial) || y >= cavemode_top) {
            continue;
          }
        }

        if (s.excludes[bt]) {
          continue;
        }

        int bl = skylight_r.get4(x, z, y),
            sl = blocklight_r.get4(x, z, y);

        int px, py;
        c.project_obliqueangle(p, px, py);

        Color top(mc::MaterialColor[bt]);
        Color side(mc::MaterialSideColor[bt]);

        apply_shading(s, bl, sl, hmval, y, top);
        apply_shading(s, bl, sl, hmval, y, side);

        switch(mc::MaterialModes[bt]) {
        case mc::Block:
          img->add_pixel(px, py - 1, top);
          img->add_pixel(px + 1, py - 1, top);
          img->add_pixel(px, py, side);
          side.darken(0x20);
          img->add_pixel(px + 1, py, side);
          break;
        case mc::HalfBlock:
          img->add_pixel(px, py, top);
          img->add_pixel(px + 1, py, top);
          break;
        case mc::TopBlock:
          img->add_pixel(px, py - 1, top);
          img->add_pixel(px + 1, py - 1, top);
          break;
        }
      }
    }
  }

  return img;
}
<commit_msg>Removed aux output<commit_after>#include <assert.h>

#include "global.h"

#include "Level.h"
#include "blocks.h"
#include "2d/cube.h"

void begin_compound(void *context, nbt::String name) {
  if (name.compare("Level") == 0) {
    ((Level*)context)->islevel = true;
  }
}

void register_int(void *context, nbt::String name, nbt::Int i) {
  Level *level = ((Level*)context);

  if (!level->islevel) {
    return;
  }

  if (name.compare("xPos") == 0) {
    level->xPos = i;
    return;
  }

  if (name.compare("zPos") == 0) {
    level->zPos = i;
    return;
  }
}

void register_byte_array(void *context, nbt::String name, nbt::ByteArray* byte_array) {
  Level *level = ((Level*)context);

  if (!level->islevel) {
    delete byte_array;
    return;
  }

  if (name.compare("Blocks") == 0) {
    level->blocks = byte_array;
    return;
  }

  if (name.compare("SkyLight") == 0) {
    level->skylight = byte_array;
    return;
  }

  if (name.compare("HeightMap") == 0) {
    level->heightmap = byte_array;
    return;
  }

  if (name.compare("BlockLight") == 0) {
    level->blocklight = byte_array;
    return;
  }
}

void error_handler(void *context, size_t where, const char *why) {
  Level *level = ((Level *)context);
  level->grammar_error = true;
  level->grammar_error_where = where;
  level->grammar_error_why = why;
}

#include <iostream>

Level::~Level(){
  if (ignore_blocks) {
    return;
  }

  if (blocks != NULL) delete blocks;
  if (skylight != NULL) delete skylight;
  if (heightmap != NULL) delete heightmap;
  if (blocklight != NULL) delete blocklight;
}

Level::Level(const char *path, bool ignore_blocks)
  : path(path), ignore_blocks(ignore_blocks)
{
  xPos = 0;
  zPos = 0;
  islevel = false;
  grammar_error = false;

  nbt::Parser parser(this);

  if (!ignore_blocks) {
    parser.register_byte_array = register_byte_array;
  }

  parser.register_int = register_int;
  parser.begin_compound = begin_compound;
  parser.error_handler = error_handler;

  try {
    parser.parse_file(path);
  } catch(nbt::bad_grammar &bg) {
    grammar_error = true;
  }
}

/**
 * Blocks[ z + ( y * ChunkSizeY(=128) + ( x * ChunkSizeY(=128) * ChunkSizeZ(=16) ) ) ];
 */
nbt::Byte bget(nbt::ByteArray *blocks, int x, int z, int y) {
  assert(x >= 0 && x < mc::MapX);
  assert(z >= 0 && z < mc::MapZ);
  assert(y >= 0 && y < mc::MapY);
  int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
  assert (p >= 0 && p < blocks->length);
  return blocks->values[p];
}

nbt::Byte bsget(nbt::ByteArray *skylight, int x, int z, int y) {
  assert(x >= 0 && x < mc::MapX);
  assert(z >= 0 && z < mc::MapZ);
  assert(y >= 0 && y < mc::MapY);
  int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
  int ap = p / 2;

  assert (ap >= 0 && ap < skylight->length);

  // force unsigned
  uint8_t bp = skylight->values[ap] & 0xff;

  if (p % 2 == 0) {
    return bp >> 4;
  }
  else {
    return bp & 0xf;
  }
}

void transform_xz(settings_t& s, int &x, int &z) {
  /*if (s->flip) {
    int t = x;
    x = z;
    z = mc::MapZ - t - 1;
  }

  if (s->invert) {
    z = mc::MapZ - z - 1;
    x = mc::MapX - x - 1;
  }*/
}

inline void apply_shading(settings_t& s, int bl, int sl, int hm, int y, Color &c) {
  // if night, darken all colors not emitting light
  if (s.night) {
    c.darken((0xd0 * (16 - bl)) / 16);
  }

  c.darken((mc::MapY - y));
}

inline bool cavemode_isopen(int bt) {
  switch(bt) {
    case mc::Air: return true;
    case mc::Leaves: return true;
    default: return false;
  }
}

inline bool cavemode_ignore_block(settings_t& s, int x, int z, int y, int bt, nbt::ByteArray *blocks, bool &cave_initial) {
  if (cave_initial) {
    if (!cavemode_isopen(bt)) {
      cave_initial = false;
      return true;
    }

    return true;
  }

  if (!cavemode_isopen(bt)) {
    if (y < s.top && cavemode_isopen(bget(blocks, x, z, y + 1))) {
      return false;
    }
  }

  return true;
}

class BlockRotation {
private:
  settings_t& s;
  nbt::ByteArray *byte_array;

  void transform_xz(int& x, int& z) {
    switch (s.rotation) {
      case 270:
        z = mc::MapZ - z - 1;
        x = mc::MapX - x - 1;
        {
          int t = x;
          x = z;
          z = mc::MapZ - t - 1;
        }
        break;
      case 180:
        z = mc::MapZ - z - 1;
        x = mc::MapX - x - 1;
        break;
      case 90:
        {
          int t = x;
          x = z;
          z = mc::MapZ - t - 1;
        }
        break;
    };
  }

public:
  BlockRotation(settings_t& s, nbt::ByteArray *byte_array)
    : s(s), byte_array(byte_array) {}

  uint8_t get8(int x, int z, int y) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    assert(y >= 0 && y < mc::MapY);
    int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
    assert (p >= 0 && p < byte_array->length);
    return byte_array->values[p];
  }

  uint8_t get8(int x, int z) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    int p = x + (z * mc::MapX);
    assert (p >= 0 && p < byte_array->length);
    return byte_array->values[p];
  }

  uint8_t get4(int x, int z, int y) {
    transform_xz(x, z);

    assert(x >= 0 && x < mc::MapX);
    assert(z >= 0 && z < mc::MapZ);
    assert(y >= 0 && y < mc::MapY);
    int p = y + (z * mc::MapY + (x * mc::MapY * mc::MapZ));
    int ap = p / 2;

    assert (ap >= 0 && ap < byte_array->length);

    // force unsigned
    uint8_t bp = byte_array->values[ap] & 0xff;

    if (p % 2 == 0) {
      return bp >> 4;
    }
    else {
      return bp & 0xf;
    }
  }
};

ImageBuffer *Level::get_image(settings_t& s) {
  ImageBuffer *img = new ImageBuffer(mc::MapX, mc::MapZ, 1);

  if (!islevel) {
    return img;
  }

  img->set_reversed(true);

  // block type
  int bt;

  for (int x = 0, mz = mc::MapZ - 1; x < mc::MapX; x++, mz--) {
    for (int y = 0, mx = 0; y < mc::MapX; y++, mx++) {
      Color base(255, 255, 255, 0);

      bt = mc::Air;

      bool cave_initial = true;

      int my;

      BlockRotation blocks_r(s, blocks);
      BlockRotation blocklight_r(s, blocklight);
      BlockRotation skylight_r(s, skylight);

      // do incremental color fill until color is opaque
      for (my = s.top; my > s.bottom; my--) {
        bt = blocks_r.get8(mx, mz, my);

        if (s.cavemode && cavemode_ignore_block(s, mx, mz, my, bt, blocks, cave_initial)) {
          continue;
        }

        if (s.excludes[bt]) {
          continue;
        }

        Color bc(mc::MaterialColor[bt]);

        int bl = blocklight_r.get4(mx, mz, my),
            sl = skylight_r.get4(mx, mz, my);

        apply_shading(s, bl, sl, 0, my, bc);

        base.underlay(bc);

        if (base.is_opaque()) {
          break;
        }
      }

      if (base.is_transparent()) {
        continue;
      }

      img->set_pixel(x, y, 0, base);
    }
  }

  return img;
}

ImageBuffer *Level::get_oblique_image(settings_t& s)
{
  ImageBuffer *img = new ImageBuffer(mc::MapX, mc::MapZ + mc::MapY, mc::MapY + mc::MapZ);

  if (!islevel) {
    return img;
  }

  Cube c(mc::MapX, mc::MapY, mc::MapZ);

  // block type
  int bt;

  BlockRotation blocks_r(s, blocks);
  BlockRotation blocklight_r(s, blocklight);
  BlockRotation skylight_r(s, skylight);

  for (int x = 0, mz = mc::MapZ - 1; x < mc::MapX; x++, mz--) {
    for (int y = 0, mx = 0; y < mc::MapX; y++, mx++) {
      bool cave_initial = true;
      int cavemode_top = s.top;

      if (s.cavemode) {
        for (int my = s.top; my > 0; my--) {
          bt = blocks_r.get8(mx, mz, y);

          if (!cavemode_isopen(bt)) {
            cavemode_top = my;
            break;
          }
        }
      }

      for (int my = s.bottom; my < s.top; my++) {
        point p(x, my, y);

        bt = blocks_r.get8(mx, mz, my);

        if (s.cavemode) {
          if (cavemode_ignore_block(s, mx, mz, my, bt, blocks, cave_initial) || my >= cavemode_top) {
            continue;
          }
        }

        if (s.excludes[bt]) {
          continue;
        }

        int bl = blocklight_r.get4(mx, mz, my),
            sl = skylight_r.get4(mx, mz, my);

        int px, py;
        c.project_oblique(p, px, py);

        Color top(mc::MaterialColor[bt]);
        apply_shading(s, bl, sl, 0, my, top);
        img->add_pixel(px, py - 1, top);

        Color side(mc::MaterialSideColor[bt]);
        apply_shading(s, bl, sl, 0, my, side);
        img->add_pixel(px, py, side);
      }
    }
  }

  return img;
}

ImageBuffer *Level::get_obliqueangle_image(settings_t& s)
{
  ImageBuffer *img = new ImageBuffer(mc::MapX * 2 + 1, mc::MapX + mc::MapY + mc::MapZ, mc::MapY + mc::MapZ * 2);

  if (!islevel) {
    return img;
  }

  Cube c(mc::MapX, mc::MapY, mc::MapZ);

  // block type
  int bt;

  BlockRotation blocks_r(s, blocks);
  BlockRotation blocklight_r(s, blocklight);
  BlockRotation skylight_r(s, skylight);
  BlockRotation heightmap_r(s, heightmap);

  for (int z = 0; z < c.z; z++) {
    for (int x = 0; x < c.x; x++) {
      bool cave_initial = true;

      int cavemode_top = s.top;

      if (s.cavemode) {
        for (int y = s.top; y > 0; y--) {
          bt = blocks_r.get8(x, z, y);

          if (!cavemode_isopen(bt)) {
            cavemode_top = y;
            break;
          }
        }
      }

      int hmval = heightmap_r.get8(x, z);

      for (int y = s.bottom; y < s.top; y++) {
        point p(x, y, z);

        bt = blocks_r.get8(x, z, y);

        if (s.cavemode) {
          if (cavemode_ignore_block(s, x, z, y, bt, blocks, cave_initial) || y >= cavemode_top) {
            continue;
          }
        }

        if (s.excludes[bt]) {
          continue;
        }

        int bl = skylight_r.get4(x, z, y),
            sl = blocklight_r.get4(x, z, y);

        int px, py;
        c.project_obliqueangle(p, px, py);

        Color top(mc::MaterialColor[bt]);
        Color side(mc::MaterialSideColor[bt]);

        apply_shading(s, bl, sl, hmval, y, top);
        apply_shading(s, bl, sl, hmval, y, side);

        switch(mc::MaterialModes[bt]) {
        case mc::Block:
          img->add_pixel(px, py - 1, top);
          img->add_pixel(px + 1, py - 1, top);
          img->add_pixel(px, py, side);
          side.darken(0x20);
          img->add_pixel(px + 1, py, side);
          break;
        case mc::HalfBlock:
          img->add_pixel(px, py, top);
          img->add_pixel(px + 1, py, top);
          break;
        case mc::TopBlock:
          img->add_pixel(px, py - 1, top);
          img->add_pixel(px + 1, py - 1, top);
          break;
        }
      }
    }
  }

  return img;
}
<|endoftext|>


<commit_before>#include "Level.h"

std::vector<Tileset>* Level::getTilesets() {
	return &m_vTilesets;
}

std::vector<Layer*>* Level::getLayers() {
	return &m_vLayers;
}
<commit_msg>every layers of a level updated and rendered<commit_after>#include "Level.h"

std::vector<Tileset>* Level::getTilesets() {
	return &m_vTilesets;
}

std::vector<Layer*>* Level::getLayers() {
	return &m_vLayers;
}

void Level::render() {
	for (int i = 0; i < m_vLayers.size(); i++) {
		m_vLayers[i]->render();
	}
}

void Level::update() {
	for (int i = 0; i < m_vLayers.size(); i++) {
		m_vLayers[i]->update();
	}
}
<|endoftext|>


<commit_before>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file ObsID.hpp
 * gpstk::ObsID - navigation system, receiver, and file specification
 * independent representation of the types of observation data that can
 * be collected.  This class is analogous to the RinexObsType class that
 * is used to represent the observation codes in a RINEX file. It is
 * intended to support at least everything in section 5.1 of the RINEX 3
 * specifications.
 */

#ifndef OBSID_HPP
#define OBSID_HPP

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <map>

#include "Exception.hpp"
#include "SatID.hpp"

namespace gpstk
{
   class ObsID;
   namespace StringUtils
   {
      /// convert this object to a string representation
      std::string asString(const ObsID& id);
      std::string asRinex3ID(const ObsID& id);
   }

   /// stream output for ObsID
   std::ostream& operator<<(std::ostream& s, const ObsID& p);

   class ObsID
   {
   public:
      /// The type of observation.
      enum ObservationType
      {
         otUnknown,
         otAny,       ///< Used to match any observation type
         otRange,     ///< pseudorange, in meters
         otPhase,     ///< accumulated phase, in meters
         otDoppler,   ///< Doppler, in Hz
         otSNR,       ///< Signal strength, in dB-Hz
         otChannel,   ///< Channel number
         otIono,      ///< Ionospheric delay (see rinex3 section 5.12)
         otSSI,       ///< Signal Strength Indicator (kinda a rinex thing)
         otLLI,       ///< Loss of Lock Indicator (another rinex thing)
         otTrackLen,  ///< Number of continuous epochs of 'good' tracking
         otUndefined,
         otLast       ///< Used to verify that all items are described at compile time
      };

      /// The frequency band this obs was collected from.
      enum CarrierBand
      {
         cbUnknown,
         cbAny,  ///< Used to match any carrier band
         cbZero, ///< Used with the channel observation type (see rinex3 section 5.13)
         cbL1,   ///< GPS L1, Galileo E2-L1-E1, SBAS L1
         cbL2,   ///< GPS L2
         cbL5,   ///< GPS L5, Galileo E5a, SBAS L5
         cbG1,   ///< Glonass G1
         cbG2,   ///< Glonass G2
         cbE5b,  ///< Galileo E5b
         cbE5ab, ///< Galileo E5a+b
         cbE6,   ///< Galileo E6
         cbL1L2, ///< Combined L1L2 (like an ionosphere free obs)
         cbUndefined,
         cbLast  ///< Used to verify that all items are described at compile time
      };

      /// The code used to collect the observation. Each of these should uniquely
      /// identify a code that was correlated against to track the signal. While the
      /// notation generally follows section 5.1 of RINEX 3, due to ambiguities in that
      /// specification some extensions are made. Note that as concrete specifications
      /// for the codes are released, this list may need to be adjusted. Specifically,
      /// this lists assumes that the same I & Q codes will be used on all three of the
      /// Galileo carriers. If that is not true, more identifers need to be allocated
      enum TrackingCode
      {
         tcUnknown,
         tcAny,     ///< Used to match any tracking code
         tcCA,      ///< Legacy GPS civil code
         tcP,       ///< Legacy GPS precise code
         tcY,       ///< Encrypted legacy GPS precise code
         tcW,       ///< Encrypted legacy GPS precise code, with codeless Z mode tracking
         tcN,       ///< Encrypted legacy GPS precise code, with squaring codeless tracking
         tcD,       ///< Encrypted legacy GPS precise code, with other codeless tracking
         tcM,       ///< Modernized GPS military unique code
         tcC2M,     ///< Modernized GPS L2 civil M code
         tcC2L,     ///< Modernized GPS L2 civil L code
         tcC2LM,    ///< Modernized GPS L2 civil M+L combined tracking (such as Trimble NetRS, Septrentrio, and ITT)
         tcI5,      ///< Modernized GPS L5 civil in-phase
         tcQ5,      ///< Modernized GPS L5 civil quadrature
         tcIQ5,     ///< Modernized GPS L5 civil I+Q combined tracking

         tcGCA,     ///< Legacy Glonass civil signal
         tcGP,      ///< Legacy Glonass precise signal

         tcA,       ///< Galileo L1 PRS code
         tcB,       ///< Galileo OS/CS/SoL code
         tcC,       ///< Galileo Dataless code
         tcBC,      ///< Galileo B+C combined tracking
         tcABC,     ///< Galileo A+B+C combined tracking
         tcIE5,     ///< Galileo L5 I code
         tcQE5,     ///< Galileo L5 Q code
         tcIQE5,    ///< Galileo L5 I+Q combined tracking
         tcUndefined,
         tcLast     ///< Used to verify that all items are described at compile time
      };

      /// empty constructor, creates a wildcard object.
      ObsID()
         : type(otUnknown), band(cbUnknown), code(tcUnknown) {};

      /// Explicit constructor
      ObsID(ObservationType ot, CarrierBand cb, TrackingCode tc)
         : type(ot), band(cb), code(tc) {};

      /// Constructor from a Rinex 3 style descriptor. If this string is 3 characters
      /// long, the system is assumed to be GPS. If this string is 4 characters long,
      /// the first character is the system designator as described in the Rinex 3
      /// specification. If the Rinex 3 style descriptor isn't currently defined,
      /// a new one is silently automatically created with a blank description for
      /// the new characters.
      ObsID(const std::string& id) throw(InvalidParameter);
      ObsID(const char* id) throw(InvalidParameter)
      { *this=ObsID(std::string(id));};

      /// Equality requires all fields to be the same
      virtual bool operator==(const ObsID& right) const;

      /// This ordering is somewhat arbitrary but is required to be able
      /// to use an ObsID as an index to a std::map. If an application needs
      /// some other ordering, inherit and override this function. One 'feature'
      /// that has been added is that an Any code/carrier/type will match
      /// any other code/carrier/type in the equality operator. The intent is to
      /// support performing an operation like "tell me if this is a pseudorange
      /// that was collected on L1 from *any* code".
      virtual bool operator<(const ObsID& right) const;

      bool operator!=(const ObsID& right) const
      { return !(operator==(right)); };

      bool operator>(const ObsID& right) const
      {  return (!operator<(right) && !operator==(right)); };

      bool operator<=(const ObsID& right) const
      { return (operator<(right) || operator==(right)); };

      bool operator>=(const ObsID& right) const
      { return !(operator<(right)); };

      /// This returns a representation of this object using the observation
      /// codes described in section 5.1 of the Rinex 3 specification. Note that
      /// this always returns a three character identifier so some information
      /// is lost because some codes are shared between satellite systems.
      std::string asRinex3ID() const;

      /// Convenience output method
      virtual std::ostream& dump(std::ostream& s) const;

      /// Destructor
      virtual ~ObsID() {};

      /// The next three methods are deprecated
      static ObservationType newObservationType(const std::string& s){};
      static CarrierBand newCarrierBand(const std::string& s){};
      static TrackingCode newTrackingCode(const std::string& s){};

      // Extend the standard identifiers with a new Rinex 3 style identifier. If the
      // specified id is already defined, an exception is thrown and the existing
      // definitions are not touched. If not then each character of the specification
      // is examined and the new ones are created. The returned ObsID can then be
      // examined for the assigned values.
      static ObsID newID(const std::string& id,
                         const std::string& desc="") throw(InvalidParameter);

      // Note that these are the only data members of objects of this class.
      ObservationType  type;
      CarrierBand      band;
      TrackingCode     code;

      /// These strings are for forming a somewhat verbose description
      static std::map< TrackingCode,    std::string > tcDesc;
      static std::map< CarrierBand,     std::string > cbDesc;
      static std::map< ObservationType, std::string > otDesc;

      /// These strings are used to translate this object to and from a
      /// rinex identifier
      static std::map< char, ObservationType> rinex2ot;
      static std::map< char, CarrierBand> rinex2cb;
      static std::map< char, TrackingCode> rinex2tc;
      static std::map< ObservationType, char > ot2Rinex;
      static std::map< CarrierBand, char > cb2Rinex;
      static std::map< TrackingCode, char> tc2Rinex;

   public:
      class Initializer
      {
      public:
         Initializer();
      };

      static Initializer singleton;

   private:
      static ObsID idCreator(const std::string& id, const std::string& desc="");

   }; // class ObsID

} // namespace gpstk
#endif   // OBSID_HPP
<commit_msg>A lot of warnings were poping up because deprecated methods 'newObservationType', 'newCarrierBand' and 'newTrackingCode' didn't return properly. Now they are 'declared but not defined'.<commit_after>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file ObsID.hpp
 * gpstk::ObsID - navigation system, receiver, and file specification
 * independent representation of the types of observation data that can
 * be collected.  This class is analogous to the RinexObsType class that
 * is used to represent the observation codes in a RINEX file. It is
 * intended to support at least everything in section 5.1 of the RINEX 3
 * specifications.
 */

#ifndef OBSID_HPP
#define OBSID_HPP

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <map>

#include "Exception.hpp"
#include "SatID.hpp"

namespace gpstk
{
   class ObsID;
   namespace StringUtils
   {
      /// convert this object to a string representation
      std::string asString(const ObsID& id);
      std::string asRinex3ID(const ObsID& id);
   }

   /// stream output for ObsID
   std::ostream& operator<<(std::ostream& s, const ObsID& p);

   class ObsID
   {
   public:
      /// The type of observation.
      enum ObservationType
      {
         otUnknown,
         otAny,       ///< Used to match any observation type
         otRange,     ///< pseudorange, in meters
         otPhase,     ///< accumulated phase, in meters
         otDoppler,   ///< Doppler, in Hz
         otSNR,       ///< Signal strength, in dB-Hz
         otChannel,   ///< Channel number
         otIono,      ///< Ionospheric delay (see rinex3 section 5.12)
         otSSI,       ///< Signal Strength Indicator (kinda a rinex thing)
         otLLI,       ///< Loss of Lock Indicator (another rinex thing)
         otTrackLen,  ///< Number of continuous epochs of 'good' tracking
         otUndefined,
         otLast       ///< Used to verify that all items are described at compile time
      };

      /// The frequency band this obs was collected from.
      enum CarrierBand
      {
         cbUnknown,
         cbAny,  ///< Used to match any carrier band
         cbZero, ///< Used with the channel observation type (see rinex3 section 5.13)
         cbL1,   ///< GPS L1, Galileo E2-L1-E1, SBAS L1
         cbL2,   ///< GPS L2
         cbL5,   ///< GPS L5, Galileo E5a, SBAS L5
         cbG1,   ///< Glonass G1
         cbG2,   ///< Glonass G2
         cbE5b,  ///< Galileo E5b
         cbE5ab, ///< Galileo E5a+b
         cbE6,   ///< Galileo E6
         cbL1L2, ///< Combined L1L2 (like an ionosphere free obs)
         cbUndefined,
         cbLast  ///< Used to verify that all items are described at compile time
      };

      /// The code used to collect the observation. Each of these should uniquely
      /// identify a code that was correlated against to track the signal. While the
      /// notation generally follows section 5.1 of RINEX 3, due to ambiguities in that
      /// specification some extensions are made. Note that as concrete specifications
      /// for the codes are released, this list may need to be adjusted. Specifically,
      /// this lists assumes that the same I & Q codes will be used on all three of the
      /// Galileo carriers. If that is not true, more identifers need to be allocated
      enum TrackingCode
      {
         tcUnknown,
         tcAny,     ///< Used to match any tracking code
         tcCA,      ///< Legacy GPS civil code
         tcP,       ///< Legacy GPS precise code
         tcY,       ///< Encrypted legacy GPS precise code
         tcW,       ///< Encrypted legacy GPS precise code, with codeless Z mode tracking
         tcN,       ///< Encrypted legacy GPS precise code, with squaring codeless tracking
         tcD,       ///< Encrypted legacy GPS precise code, with other codeless tracking
         tcM,       ///< Modernized GPS military unique code
         tcC2M,     ///< Modernized GPS L2 civil M code
         tcC2L,     ///< Modernized GPS L2 civil L code
         tcC2LM,    ///< Modernized GPS L2 civil M+L combined tracking (such as Trimble NetRS, Septrentrio, and ITT)
         tcI5,      ///< Modernized GPS L5 civil in-phase
         tcQ5,      ///< Modernized GPS L5 civil quadrature
         tcIQ5,     ///< Modernized GPS L5 civil I+Q combined tracking

         tcGCA,     ///< Legacy Glonass civil signal
         tcGP,      ///< Legacy Glonass precise signal

         tcA,       ///< Galileo L1 PRS code
         tcB,       ///< Galileo OS/CS/SoL code
         tcC,       ///< Galileo Dataless code
         tcBC,      ///< Galileo B+C combined tracking
         tcABC,     ///< Galileo A+B+C combined tracking
         tcIE5,     ///< Galileo L5 I code
         tcQE5,     ///< Galileo L5 Q code
         tcIQE5,    ///< Galileo L5 I+Q combined tracking
         tcUndefined,
         tcLast     ///< Used to verify that all items are described at compile time
      };

      /// empty constructor, creates a wildcard object.
      ObsID()
         : type(otUnknown), band(cbUnknown), code(tcUnknown) {};

      /// Explicit constructor
      ObsID(ObservationType ot, CarrierBand cb, TrackingCode tc)
         : type(ot), band(cb), code(tc) {};

      /// Constructor from a Rinex 3 style descriptor. If this string is 3 characters
      /// long, the system is assumed to be GPS. If this string is 4 characters long,
      /// the first character is the system designator as described in the Rinex 3
      /// specification. If the Rinex 3 style descriptor isn't currently defined,
      /// a new one is silently automatically created with a blank description for
      /// the new characters.
      ObsID(const std::string& id) throw(InvalidParameter);
      ObsID(const char* id) throw(InvalidParameter)
      { *this=ObsID(std::string(id));};

      /// Equality requires all fields to be the same
      virtual bool operator==(const ObsID& right) const;

      /// This ordering is somewhat arbitrary but is required to be able
      /// to use an ObsID as an index to a std::map. If an application needs
      /// some other ordering, inherit and override this function. One 'feature'
      /// that has been added is that an Any code/carrier/type will match
      /// any other code/carrier/type in the equality operator. The intent is to
      /// support performing an operation like "tell me if this is a pseudorange
      /// that was collected on L1 from *any* code".
      virtual bool operator<(const ObsID& right) const;

      bool operator!=(const ObsID& right) const
      { return !(operator==(right)); };

      bool operator>(const ObsID& right) const
      {  return (!operator<(right) && !operator==(right)); };

      bool operator<=(const ObsID& right) const
      { return (operator<(right) || operator==(right)); };

      bool operator>=(const ObsID& right) const
      { return !(operator<(right)); };

      /// This returns a representation of this object using the observation
      /// codes described in section 5.1 of the Rinex 3 specification. Note that
      /// this always returns a three character identifier so some information
      /// is lost because some codes are shared between satellite systems.
      std::string asRinex3ID() const;

      /// Convenience output method
      virtual std::ostream& dump(std::ostream& s) const;

      /// Destructor
      virtual ~ObsID() {};

      /// The next three methods are deprecated
      static ObservationType newObservationType(const std::string& s);
      static CarrierBand newCarrierBand(const std::string& s);
      static TrackingCode newTrackingCode(const std::string& s);

      // Extend the standard identifiers with a new Rinex 3 style identifier. If the
      // specified id is already defined, an exception is thrown and the existing
      // definitions are not touched. If not then each character of the specification
      // is examined and the new ones are created. The returned ObsID can then be
      // examined for the assigned values.
      static ObsID newID(const std::string& id,
                         const std::string& desc="") throw(InvalidParameter);

      // Note that these are the only data members of objects of this class.
      ObservationType  type;
      CarrierBand      band;
      TrackingCode     code;

      /// These strings are for forming a somewhat verbose description
      static std::map< TrackingCode,    std::string > tcDesc;
      static std::map< CarrierBand,     std::string > cbDesc;
      static std::map< ObservationType, std::string > otDesc;

      /// These strings are used to translate this object to and from a
      /// rinex identifier
      static std::map< char, ObservationType> rinex2ot;
      static std::map< char, CarrierBand> rinex2cb;
      static std::map< char, TrackingCode> rinex2tc;
      static std::map< ObservationType, char > ot2Rinex;
      static std::map< CarrierBand, char > cb2Rinex;
      static std::map< TrackingCode, char> tc2Rinex;

   public:
      class Initializer
      {
      public:
         Initializer();
      };

      static Initializer singleton;

   private:
      static ObsID idCreator(const std::string& id, const std::string& desc="");

   }; // class ObsID

} // namespace gpstk
#endif   // OBSID_HPP
<|endoftext|>


<commit_before>#include "OrbitalCamera.h"
#include "Keyboard.h"
#include "Mouse.h"
#include <glm/gtx/rotate_vector.hpp>//GLM_GTX_rotate_vector
OrbitalCamera::OrbitalCamera(float w, float h):
   Camera(w,h),
   phi(0),
   theta(0),
   radius(3),
   Cam_Rot_Speed(2*M_PI),
   Cam_Zoom_Speed(3.0)
   {

   }
void OrbitalCamera::update(const Context * ctx)
{
   glm::vec3 rotate(0.0);
   if(Mouse::pressed(GLFW_MOUSE_BUTTON_LEFT))
   {
      if(Keyboard::isKeyDown(GLFW_KEY_LEFT_SHIFT))
      {
         radius += (Mouse::getLastY() - Mouse::getY())/(float)(ctx->getWindowHeight())/2.0 * Cam_Zoom_Speed;
      }

      else
      {

         rotate.y = (Mouse::getLastY() - Mouse::getY())/(float)(ctx->getWindowHeight())/2.0 * Cam_Rot_Speed;
         rotate.x = (Mouse::getLastX() - Mouse::getX())/(float)(ctx->getWindowWidth())/2.0 * Cam_Rot_Speed;
         phi += rotate.x;
         theta -= rotate.y;
         rotate.z = 0;
      }

   }
   glm::vec3 position(0,0,radius);
   glm::rotateY(position,phi);
   glm::rotateX(position,theta);
   setPosition(position);
   lookAt(glm::vec3(0,0,0));
}

<commit_msg>Completed orbital camera<commit_after>#include "OrbitalCamera.h"
#include "Keyboard.h"
#include "Mouse.h"
#include <glm/gtx/rotate_vector.hpp>//GLM_GTX_rotate_vector
OrbitalCamera::OrbitalCamera(float w, float h):
   Camera(w,h),
   phi(0),
   theta(0),
   radius(3),
   Cam_Rot_Speed(2*M_PI),
   Cam_Zoom_Speed(3.0)
   {

   }
void OrbitalCamera::update(const Context * ctx)
{
   glm::vec3 rotate(0.0);
   if(Mouse::pressed(GLFW_MOUSE_BUTTON_LEFT))
   {
      if(Keyboard::isKeyDown(GLFW_KEY_LEFT_SHIFT))
      {
         radius += (Mouse::getLastY() - Mouse::getY())/(float)(ctx->getWindowHeight())/2.0 * Cam_Zoom_Speed;
      }

      else
      {

         rotate.y = (Mouse::getLastY() - Mouse::getY())/(float)(ctx->getWindowHeight())/2.0 * Cam_Rot_Speed;
         rotate.x = (Mouse::getLastX() - Mouse::getX())/(float)(ctx->getWindowWidth())/2.0 * Cam_Rot_Speed;
         phi += rotate.y;
         theta += rotate.x;
         rotate.z = 0;
      }

   }
   glm::vec3 position(0,0,radius);
   position = glm::rotateX(position,phi);
   position = glm::rotateY(position,theta);

   setPosition(position);
   lookAt(glm::vec3(0,0,0));
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qmlmediabase_p.h"

#include <QtCore/qabstractanimation.h>
#include <QtCore/qcoreevent.h>

#include <qmediaplayercontrol.h>
#include <qmediaservice.h>
#include <qmediaserviceprovider.h>
#include <qmetadatacontrol.h>
#include <qmetadatacontrolmetaobject_p.h>

QTM_BEGIN_NAMESPACE

class QmlMediaBasePlayerControl : public QMediaPlayerControl
{
public:
    QmlMediaBasePlayerControl(QObject *parent)
        : QMediaPlayerControl(parent)
    {
    }

    QMediaPlayer::State state() const { return QMediaPlayer::StoppedState; }
    QMediaPlayer::MediaStatus mediaStatus() const { return QMediaPlayer::NoMedia; }

    qint64 duration() const { return 0; }
    qint64 position() const { return 0; }
    void setPosition(qint64) {}
    int volume() const { return 100; }
    void setVolume(int) {}
    bool isMuted() const { return false; }
    void setMuted(bool) {}
    int bufferStatus() const { return 0; }
    bool isVideoAvailable() const { return false; }
    bool isSeekable() const { return false; }
    QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
    qreal playbackRate() const { return 1; }
    void setPlaybackRate(qreal) {}
    QMediaContent media() const { return QMediaContent(); }
    const QIODevice *mediaStream() const { return 0; }
    void setMedia(const QMediaContent &, QIODevice *) {}

    void play() {}
    void pause() {}
    void stop() {}
};

class QmlMediaBaseAnimation : public QAbstractAnimation
{
public:
    QmlMediaBaseAnimation(QmlMediaBase *media)
        : m_media(media)
    {
    }

    int duration() const { return -1; }

protected:
    void updateCurrentTime(int)
    {
        if (m_media->m_state == QMediaPlayer::PlayingState)
            emit m_media->positionChanged();
        if (m_media->m_status == QMediaPlayer::BufferingMedia || QMediaPlayer::StalledMedia)
            emit m_media->bufferStatusChanged();
    }

private:
    QmlMediaBase *m_media;
};

void QmlMediaBase::_q_stateChanged(QMediaPlayer::State state)
{
    if (state != m_state) {
        m_state = state;

        emit playingChanged();
        emit pausedChanged();

        if (m_animation->state() != QAbstractAnimation::Running
                && (m_state == QMediaPlayer::PlayingState
                || m_status == QMediaPlayer::BufferingMedia
                || m_status == QMediaPlayer::StalledMedia)) {
            m_animation->start();
        } else {
            m_animation->stop();
        }
    }
}

void QmlMediaBase::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
    if (status != m_status) {
        m_status = status;

        emit statusChanged();

        if (m_animation->state() != QAbstractAnimation::Running
                && (m_state == QMediaPlayer::PlayingState
                || m_status == QMediaPlayer::BufferingMedia
                || m_status == QMediaPlayer::StalledMedia)) {
            m_animation->start();
        } else {
            m_animation->stop();
        }
    }
}

void QmlMediaBase::_q_error(QMediaPlayer::Error error, const QString &errorString)
{
    m_error = error;
    m_errorString = errorString;

    emit errorChanged();
}

void QmlMediaBase::_q_metaDataChanged()
{
    m_metaObject->metaDataChanged();
}

QmlMediaBase::QmlMediaBase()
    : m_mediaService(0)
    , m_playerControl(0)
    , m_mediaProvider(0)
    , m_metaDataControl(0)
    , m_metaObject(0)
    , m_animation(0)
    , m_state(QMediaPlayer::StoppedState)
    , m_status(QMediaPlayer::NoMedia)
    , m_error(QMediaPlayer::NoError)
{
}

QmlMediaBase::~QmlMediaBase()
{
}

void QmlMediaBase::shutdown()
{
    delete m_metaObject;

    if (m_mediaProvider)
        m_mediaProvider->releaseService(m_mediaService);

    delete m_animation;

}

void QmlMediaBase::setObject(QObject *object)
{
    if ((m_mediaProvider = QMediaServiceProvider::defaultServiceProvider())) {
        if ((m_mediaService = m_mediaProvider->requestService(Q_MEDIASERVICE_MEDIAPLAYER))) {
            m_playerControl = qobject_cast<QMediaPlayerControl *>(
                    m_mediaService->control(QMediaPlayerControl_iid));
            m_metaDataControl = qobject_cast<QMetaDataControl *>(
                    m_mediaService->control(QMetaDataControl_iid));
        }
    }

    if (m_playerControl) {
        QObject::connect(m_playerControl, SIGNAL(stateChanged(QMediaPlayer::State)),
                object, SLOT(_q_stateChanged(QMediaPlayer::State)));
        QObject::connect(m_playerControl, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                object, SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
        QObject::connect(m_playerControl, SIGNAL(mediaChanged(QMediaContent)),
                object, SIGNAL(sourceChanged()));
        QObject::connect(m_playerControl, SIGNAL(durationChanged(qint64)),
                object, SIGNAL(durationChanged()));
        QObject::connect(m_playerControl, SIGNAL(positionChanged(qint64)),
                object, SIGNAL(positionChanged()));
        QObject::connect(m_playerControl, SIGNAL(volumeChanged(int)),
                object, SIGNAL(volumeChanged()));
        QObject::connect(m_playerControl, SIGNAL(mutedChanged(bool)),
                object, SIGNAL(mutedChanged()));

        m_animation = new QmlMediaBaseAnimation(this);
    } else {
        m_playerControl = new QmlMediaBasePlayerControl(object);
    }

    if (m_metaDataControl) {
        m_metaObject = new QMetaDataControlMetaObject(m_metaDataControl, object);

        QObject::connect(m_metaDataControl, SIGNAL(metaDataChanged()),
                object, SLOT(_q_metaDataChanged()));
    }
}

QUrl QmlMediaBase::source() const
{
    return m_playerControl->media().canonicalUrl();
}

void QmlMediaBase::setSource(const QUrl &url)
{
    m_playerControl->setMedia(QMediaContent(url), 0);
}

bool QmlMediaBase::isPlaying() const
{
    return m_state != QMediaPlayer::StoppedState;
}

void QmlMediaBase::setPlaying(bool playing)
{
    if (playing && m_state == QMediaPlayer::StoppedState)
        m_playerControl->play();
    else if (!playing)
        m_playerControl->stop();
}

bool QmlMediaBase::isPaused() const
{
    return m_state == QMediaPlayer::PausedState;
}

void QmlMediaBase::setPaused(bool paused)
{
    if (paused && m_state == QMediaPlayer::PlayingState)
        m_playerControl->pause();
    if (!paused && m_state == QMediaPlayer::PausedState)
        m_playerControl->play();
}

QmlMedia::Status QmlMediaBase::status() const
{
    return QmlMedia::Status(m_status);
}

int QmlMediaBase::duration() const
{
    return m_playerControl->duration();
}

int QmlMediaBase::position() const
{
    return m_playerControl->position();

}

void QmlMediaBase::setPosition(int position)
{
    m_playerControl->setPosition(position);
}

qreal QmlMediaBase::volume() const
{
    return qreal(m_playerControl->volume()) / 100;
}

void QmlMediaBase::setVolume(qreal volume)
{
    m_playerControl->setVolume(volume * 100);
}

bool QmlMediaBase::isMuted() const
{
    return m_playerControl->isMuted();
}

void QmlMediaBase::setMuted(bool muted)
{
    m_playerControl->setMuted(muted);
}

int QmlMediaBase::bufferStatus() const
{
    return m_playerControl->bufferStatus();
}

bool QmlMediaBase::isSeekable() const
{
    return m_playerControl->isSeekable();
}

qreal QmlMediaBase::playbackRate() const
{
    return m_playerControl->playbackRate();
}

void QmlMediaBase::setPlaybackRate(qreal rate)
{
    m_playerControl->setPlaybackRate(rate);
}

QmlMedia::Error QmlMediaBase::error() const
{
    return QmlMedia::Error(m_error);
}

QString QmlMediaBase::errorString() const
{
    return m_errorString;
}

QTM_END_NAMESPACE

<commit_msg>Fix emission of position and buffer status signal.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qmlmediabase_p.h"

#include <QtCore/qabstractanimation.h>
#include <QtCore/qcoreevent.h>

#include <qmediaplayercontrol.h>
#include <qmediaservice.h>
#include <qmediaserviceprovider.h>
#include <qmetadatacontrol.h>
#include <qmetadatacontrolmetaobject_p.h>

QTM_BEGIN_NAMESPACE

class QmlMediaBasePlayerControl : public QMediaPlayerControl
{
public:
    QmlMediaBasePlayerControl(QObject *parent)
        : QMediaPlayerControl(parent)
    {
    }

    QMediaPlayer::State state() const { return QMediaPlayer::StoppedState; }
    QMediaPlayer::MediaStatus mediaStatus() const { return QMediaPlayer::NoMedia; }

    qint64 duration() const { return 0; }
    qint64 position() const { return 0; }
    void setPosition(qint64) {}
    int volume() const { return 100; }
    void setVolume(int) {}
    bool isMuted() const { return false; }
    void setMuted(bool) {}
    int bufferStatus() const { return 0; }
    bool isVideoAvailable() const { return false; }
    bool isSeekable() const { return false; }
    QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
    qreal playbackRate() const { return 1; }
    void setPlaybackRate(qreal) {}
    QMediaContent media() const { return QMediaContent(); }
    const QIODevice *mediaStream() const { return 0; }
    void setMedia(const QMediaContent &, QIODevice *) {}

    void play() {}
    void pause() {}
    void stop() {}
};

class QmlMediaBaseAnimation : public QAbstractAnimation
{
public:
    QmlMediaBaseAnimation(QmlMediaBase *media)
        : m_media(media)
    {
    }

    int duration() const { return -1; }

protected:
    void updateCurrentTime(int)
    {
        if (m_media->m_state == QMediaPlayer::PlayingState)
            emit m_media->positionChanged();
        if (m_media->m_status == QMediaPlayer::BufferingMedia || QMediaPlayer::StalledMedia)
            emit m_media->bufferStatusChanged();
    }

private:
    QmlMediaBase *m_media;
};

void QmlMediaBase::_q_stateChanged(QMediaPlayer::State state)
{
    if (state != m_state) {
        m_state = state;

        emit playingChanged();
        emit pausedChanged();

        if (m_state == QMediaPlayer::PlayingState
                || m_status == QMediaPlayer::BufferingMedia
                || m_status == QMediaPlayer::StalledMedia) {
            m_animation->start();
        } else {
            m_animation->stop();
        }
    }
}

void QmlMediaBase::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
    if (status != m_status) {
        m_status = status;

        emit statusChanged();

        if (m_state == QMediaPlayer::PlayingState
                || m_status == QMediaPlayer::BufferingMedia
                || m_status == QMediaPlayer::StalledMedia) {
            m_animation->start();
        } else {
            m_animation->stop();
        }
    }
}

void QmlMediaBase::_q_error(QMediaPlayer::Error error, const QString &errorString)
{
    m_error = error;
    m_errorString = errorString;

    emit errorChanged();
}

void QmlMediaBase::_q_metaDataChanged()
{
    m_metaObject->metaDataChanged();
}

QmlMediaBase::QmlMediaBase()
    : m_mediaService(0)
    , m_playerControl(0)
    , m_mediaProvider(0)
    , m_metaDataControl(0)
    , m_metaObject(0)
    , m_animation(0)
    , m_state(QMediaPlayer::StoppedState)
    , m_status(QMediaPlayer::NoMedia)
    , m_error(QMediaPlayer::NoError)
{
}

QmlMediaBase::~QmlMediaBase()
{
}

void QmlMediaBase::shutdown()
{
    delete m_metaObject;

    if (m_mediaProvider)
        m_mediaProvider->releaseService(m_mediaService);

    delete m_animation;

}

void QmlMediaBase::setObject(QObject *object)
{
    if ((m_mediaProvider = QMediaServiceProvider::defaultServiceProvider())) {
        if ((m_mediaService = m_mediaProvider->requestService(Q_MEDIASERVICE_MEDIAPLAYER))) {
            m_playerControl = qobject_cast<QMediaPlayerControl *>(
                    m_mediaService->control(QMediaPlayerControl_iid));
            m_metaDataControl = qobject_cast<QMetaDataControl *>(
                    m_mediaService->control(QMetaDataControl_iid));
        }
    }

    if (m_playerControl) {
        QObject::connect(m_playerControl, SIGNAL(stateChanged(QMediaPlayer::State)),
                object, SLOT(_q_stateChanged(QMediaPlayer::State)));
        QObject::connect(m_playerControl, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                object, SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
        QObject::connect(m_playerControl, SIGNAL(mediaChanged(QMediaContent)),
                object, SIGNAL(sourceChanged()));
        QObject::connect(m_playerControl, SIGNAL(durationChanged(qint64)),
                object, SIGNAL(durationChanged()));
        QObject::connect(m_playerControl, SIGNAL(positionChanged(qint64)),
                object, SIGNAL(positionChanged()));
        QObject::connect(m_playerControl, SIGNAL(volumeChanged(int)),
                object, SIGNAL(volumeChanged()));
        QObject::connect(m_playerControl, SIGNAL(mutedChanged(bool)),
                object, SIGNAL(mutedChanged()));

        m_animation = new QmlMediaBaseAnimation(this);
    } else {
        m_playerControl = new QmlMediaBasePlayerControl(object);
    }

    if (m_metaDataControl) {
        m_metaObject = new QMetaDataControlMetaObject(m_metaDataControl, object);

        QObject::connect(m_metaDataControl, SIGNAL(metaDataChanged()),
                object, SLOT(_q_metaDataChanged()));
    }
}

QUrl QmlMediaBase::source() const
{
    return m_playerControl->media().canonicalUrl();
}

void QmlMediaBase::setSource(const QUrl &url)
{
    m_playerControl->setMedia(QMediaContent(url), 0);
}

bool QmlMediaBase::isPlaying() const
{
    return m_state != QMediaPlayer::StoppedState;
}

void QmlMediaBase::setPlaying(bool playing)
{
    if (playing && m_state == QMediaPlayer::StoppedState)
        m_playerControl->play();
    else if (!playing)
        m_playerControl->stop();
}

bool QmlMediaBase::isPaused() const
{
    return m_state == QMediaPlayer::PausedState;
}

void QmlMediaBase::setPaused(bool paused)
{
    if (paused && m_state == QMediaPlayer::PlayingState)
        m_playerControl->pause();
    if (!paused && m_state == QMediaPlayer::PausedState)
        m_playerControl->play();
}

QmlMedia::Status QmlMediaBase::status() const
{
    return QmlMedia::Status(m_status);
}

int QmlMediaBase::duration() const
{
    return m_playerControl->duration();
}

int QmlMediaBase::position() const
{
    return m_playerControl->position();

}

void QmlMediaBase::setPosition(int position)
{
    m_playerControl->setPosition(position);
}

qreal QmlMediaBase::volume() const
{
    return qreal(m_playerControl->volume()) / 100;
}

void QmlMediaBase::setVolume(qreal volume)
{
    m_playerControl->setVolume(volume * 100);
}

bool QmlMediaBase::isMuted() const
{
    return m_playerControl->isMuted();
}

void QmlMediaBase::setMuted(bool muted)
{
    m_playerControl->setMuted(muted);
}

int QmlMediaBase::bufferStatus() const
{
    return m_playerControl->bufferStatus();
}

bool QmlMediaBase::isSeekable() const
{
    return m_playerControl->isSeekable();
}

qreal QmlMediaBase::playbackRate() const
{
    return m_playerControl->playbackRate();
}

void QmlMediaBase::setPlaybackRate(qreal rate)
{
    m_playerControl->setPlaybackRate(rate);
}

QmlMedia::Error QmlMediaBase::error() const
{
    return QmlMedia::Error(m_error);
}

QString QmlMediaBase::errorString() const
{
    return m_errorString;
}

QTM_END_NAMESPACE

<|endoftext|>