<commit_before>#include "pybulletphysics.h"

static void
Quaternion_dealloc(bulletphysics_QuaternionObject* self)
{
        delete(self->quaternion);
        self->ob_type->tp_free((PyObject*)self);
}

static PyObject*
Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	float x = 0.0;
	float y = 0.0;
	float z = 0.0;
	float w = 0.0;
	if (!PyArg_ParseTuple(args, "ffff", &x, &y, &z, &w)) {
        	return NULL;
    	}

        bulletphysics_QuaternionObject *self = (bulletphysics_QuaternionObject *)type->tp_alloc(type, 0);
        if (self != NULL) {
                self->quaternion = new btQuaternion(x, y, z, w);
        }
        return (PyObject *)self;
}

PyTypeObject bulletphysics_QuaternionType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "bulletphysics.Quaternion", /*tp_name*/
    sizeof(bulletphysics_QuaternionObject), /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)Quaternion_dealloc,    /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "Quaternion object",           /* tp_doc */
};

PyObject *new_pyquaternion_from_quaternion(btQuaternion q) {
        bulletphysics_QuaternionObject *py_quaternion = (bulletphysics_QuaternionObject *)bulletphysics_QuaternionType.tp_alloc(&bulletphysics_QuaternionType, 0);
        if (py_quaternion) {
                py_quaternion->quaternion = new btQuaternion(q.getX(), q.getY(), q.getZ(), q.getW());
                Py_INCREF(py_quaternion);
        }
        return (PyObject *)py_quaternion;
}

static PyObject *
Quaternion_getX(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getX());
}

static PyObject *
Quaternion_getY(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getY());
}

static PyObject *
Quaternion_getZ(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getZ());
}

static PyObject *
Quaternion_getW(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getW());
}

static PyObject *
Quaternion_getAxis(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
	return new_pyvector3_from_vector(self->quaternion->getAxis());
}

static PyObject *
Quaternion_getAngle(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
	return PyFloat_FromDouble(self->quaternion->getAngle());
}

static PyMethodDef Quaternion_methods[] = {
    {"getX", (PyCFunction)Quaternion_getX, METH_VARARGS, NULL },
    {"getY", (PyCFunction)Quaternion_getY, METH_VARARGS, NULL },
    {"getZ", (PyCFunction)Quaternion_getZ, METH_VARARGS, NULL },
    {"getW", (PyCFunction)Quaternion_getW, METH_VARARGS, NULL },
    {"getAxis", (PyCFunction)Quaternion_getAxis, METH_VARARGS, NULL },
    {"getAngle", (PyCFunction)Quaternion_getAngle, METH_VARARGS, NULL },
    {NULL, NULL, 0, NULL}
};

void pybulletphysics_add_Quaternion(PyObject *module) {
	bulletphysics_QuaternionType.tp_methods = Quaternion_methods;
	bulletphysics_QuaternionType.tp_new = Quaternion_new;

        if (PyType_Ready(&bulletphysics_QuaternionType) < 0)
                return;

	Py_INCREF(&bulletphysics_QuaternionType);

        PyModule_AddObject(module, "Quaternion", (PyObject *)&bulletphysics_QuaternionType);
}
<commit_msg>added setRotation() to Quaternion<commit_after>#include "pybulletphysics.h"

extern PyTypeObject bulletphysics_Vector3Type;

static void
Quaternion_dealloc(bulletphysics_QuaternionObject* self)
{
        delete(self->quaternion);
        self->ob_type->tp_free((PyObject*)self);
}

static PyObject*
Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	float x = 0.0;
	float y = 0.0;
	float z = 0.0;
	float w = 0.0;
	if (!PyArg_ParseTuple(args, "ffff", &x, &y, &z, &w)) {
        	return NULL;
    	}

        bulletphysics_QuaternionObject *self = (bulletphysics_QuaternionObject *)type->tp_alloc(type, 0);
        if (self != NULL) {
                self->quaternion = new btQuaternion(x, y, z, w);
        }
        return (PyObject *)self;
}

PyTypeObject bulletphysics_QuaternionType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "bulletphysics.Quaternion", /*tp_name*/
    sizeof(bulletphysics_QuaternionObject), /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)Quaternion_dealloc,    /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "Quaternion object",           /* tp_doc */
};

PyObject *new_pyquaternion_from_quaternion(btQuaternion q) {
        bulletphysics_QuaternionObject *py_quaternion = (bulletphysics_QuaternionObject *)bulletphysics_QuaternionType.tp_alloc(&bulletphysics_QuaternionType, 0);
        if (py_quaternion) {
                py_quaternion->quaternion = new btQuaternion(q.getX(), q.getY(), q.getZ(), q.getW());
                Py_INCREF(py_quaternion);
        }
        return (PyObject *)py_quaternion;
}

static PyObject *
Quaternion_getX(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getX());
}

static PyObject *
Quaternion_getY(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getY());
}

static PyObject *
Quaternion_getZ(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getZ());
}

static PyObject *
Quaternion_getW(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        return PyFloat_FromDouble(self->quaternion->getW());
}

static PyObject *
Quaternion_getAxis(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
	return new_pyvector3_from_vector(self->quaternion->getAxis());
}

static PyObject *
Quaternion_getAngle(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
	return PyFloat_FromDouble(self->quaternion->getAngle());
}

static PyObject *
Quaternion_setRotation(bulletphysics_QuaternionObject *self, PyObject *args, PyObject *kwds) {
        bulletphysics_Vector3Object *py_vector3 = NULL;
        float angle = 0.0;
        if (!PyArg_ParseTuple(args, "Of", &py_vector3, &angle)) {
                return NULL;
        }
        pybulletphysics_checktype(py_vector3, Vector3);
	self->quaternion->setRotation(*(py_vector3->vector), angle);
	Py_INCREF(Py_None);
	return Py_None;
}

static PyMethodDef Quaternion_methods[] = {
    {"getX", (PyCFunction)Quaternion_getX, METH_VARARGS, NULL },
    {"getY", (PyCFunction)Quaternion_getY, METH_VARARGS, NULL },
    {"getZ", (PyCFunction)Quaternion_getZ, METH_VARARGS, NULL },
    {"getW", (PyCFunction)Quaternion_getW, METH_VARARGS, NULL },
    {"getAxis", (PyCFunction)Quaternion_getAxis, METH_VARARGS, NULL },
    {"getAngle", (PyCFunction)Quaternion_getAngle, METH_VARARGS, NULL },
    {"setRotation", (PyCFunction)Quaternion_setRotation, METH_VARARGS, NULL },
    {NULL, NULL, 0, NULL}
};

void pybulletphysics_add_Quaternion(PyObject *module) {
	bulletphysics_QuaternionType.tp_methods = Quaternion_methods;
	bulletphysics_QuaternionType.tp_new = Quaternion_new;

        if (PyType_Ready(&bulletphysics_QuaternionType) < 0)
                return;

	Py_INCREF(&bulletphysics_QuaternionType);

        PyModule_AddObject(module, "Quaternion", (PyObject *)&bulletphysics_QuaternionType);
}
<|endoftext|>


<commit_before>#include "Rasterizer.hpp"
#include <cmath>
#include <algorithm>
#include <float.h>
#include <cstdio>
#include <cassert>
#include "stb_image.h"

using std::modf;

Rasterizer::Rasterizer(void* pixels) :
m_pixels(static_cast<unsigned*>(pixels))
{
    int n;
    m_texture = stbi_load("texture.png", &m_texx, &m_texy, &n, 3);
    m_mode = ERM_TEXTURES;
}

Rasterizer::~Rasterizer()
{
    stbi_image_free(m_texture);
}

static inline float crossProduct(float ax, float ay, float bx, float by)
{
    return ax * by - ay * bx;
}

static inline int min(int a, int b, int c)
{
    return std::min(a, std::min(b, c));
}

static inline int max(int a, int b, int c)
{
    return std::max(a, std::max(b, c));
}

static inline void sepcolor(unsigned c, int& r, int& g, int& b)
{
    r = (c >> 16) & 0xff;
    g = (c >> 8) & 0xff;
    b = (c >> 0) & 0xff;
}

static inline unsigned mix3colors(unsigned c1, float v1, unsigned c2, float v2, unsigned c3, float v3)
{
    int r1, g1, b1;
    int r2, g2, b2;
    int r3, g3, b3;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    sepcolor(c3, r3, g3, b3);
    int rf = r1 * v1 + r2 * v2 + r3 * v3;
    int gf = g1 * v1 + g2 * v2 + g3 * v3;
    int bf = b1 * v1 + b2 * v2 + b3 * v3;
    return (rf << 16) + (gf << 8) + bf;
}

static inline unsigned mul2colors(unsigned c1, unsigned c2)
{
    int r1, g1, b1;
    int r2, g2, b2;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    int rf = (r1 * r2) / 255;
    int gf = (g1 * g2) / 255;
    int bf = (b1 * b2) / 255;
    assert(0 <= rf && rf <= 255);
    assert(0 <= gf && gf <= 255);
    assert(0 <= bf && bf <= 255);
    return (rf << 16) + (gf << 8) + bf;
}

static void adjustToView(int& x1, int& y1, int& x2, int& y2)
{
    x1 = std::max(0, std::min(x1, 640 - 1));
    y1 = std::max(0, std::min(y1, 480 - 1));
    x2 = std::max(0, std::min(x2, 640 - 1));
    y2 = std::max(0, std::min(y2, 480 - 1));
}

static unsigned rgbf(float r, float g, float b)
{
    const int rf = std::max(0, std::min<int>(255, r * 255.f));
    const int gf = std::max(0, std::min<int>(255, g * 255.f));
    const int bf = std::max(0, std::min<int>(255, b * 255.f));
    return (rf << 16) + (gf << 8) + bf;
}

static float normalizeTCoords(float x)
{
    float u;
    x = modf(x, &u);
    return std::fabs(x);
}

void Rasterizer::rasterize()
{
    for(int i = 0; i < 640 * 480; ++i)
        m_depthbuffer[i] = FLT_MAX;

    for(int i = 0; i < 640 * 480; ++i)
        m_pixels[i] = 0x202020; //very dark gray

    for(int i = 0; i < (int)m_vertices.size(); i += 3)
    {
        int x1 = m_vertices[i].x;
        int y1 = m_vertices[i].y;
        unsigned c1 = m_vertices[i].color;
        float d1 = m_vertices[i].depth;
        float u1 = m_vertices[i].u;
        float v1 = m_vertices[i].v;

        int x2 = m_vertices[i + 1].x;
        int y2 = m_vertices[i + 1].y;
        unsigned c2 = m_vertices[i + 1].color;
        float d2 = m_vertices[i + 1].depth;
        float u2 = m_vertices[i + 1].u;
        float v2 = m_vertices[i + 1].v;

        int x3 = m_vertices[i + 2].x;
        int y3 = m_vertices[i + 2].y;
        unsigned c3 = m_vertices[i + 2].color;
        float d3 = m_vertices[i + 2].depth;
        float u3 = m_vertices[i + 2].u;
        float v3 = m_vertices[i + 2].v;

        //don't render triangles that might have been incorrectly
        //casted due to being behind the camera
        if(d1 < 0.f || d2 < 0.f || d3 < 0.f)
            continue;

        int maxX = max(x1, x2, x3);
        int minX = min(x1, x2, x3);
        int maxY = max(y1, y2, y3);
        int minY = min(y1, y2, y3);

        //clip
        adjustToView(minX, minY, maxX, maxY);

        for(int x = minX; x <= maxX; ++x)
        {
            for(int y = minY; y <= maxY; ++y)
            {
                const float w2 = crossProduct(x - x1, y - y1, x3 - x1, y3 - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                const float w3 = crossProduct(x2 - x1, y2 - y1, x - x1, y - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                if((w2 >= 0) && (w3 >= 0) && (w2 + w3 <= 1))
                {
                    const float w1 = 1.f - w2 - w3;
                    const float depth = d1 * w1 + d2 * w2 + d3 * w3;
                    if(canSetPixel(x, y, depth))
                    {
                        const unsigned color = mix3colors(c1, w1, c2, w2, c3, w3);
                        const float u = normalizeTCoords(u1 * w1 + u2 * w2 + u3 * w3);
                        const float v = normalizeTCoords(v1 * w1 + v2 * w2 + v3 * w3);
                        const unsigned texel = getTexel(u, v);
                        switch(m_mode)
                        {
                            case ERM_COLORS:
                                setPixel(x, y, color, depth);
                                break;
                            case ERM_TEXTURES:
                                setPixel(x, y, texel, depth);
                                break;
                            case ERM_COLORS_TEXTURES:
                                setPixel(x, y, mul2colors(color, texel), depth);
                                break;
                            case ERM_UV_RED_BLUE:
                                setPixel(x, y, rgbf(u, 0.f, v), depth);
                                break;
                        }//switch m_mode
                    }//can set pixel
                }//inside
            }//for y
        }//for x
    }//for each triangle
}

void Rasterizer::clear()
{
    m_vertices.clear();
}

void Rasterizer::addVertex(int x, int y, unsigned color, float depth, float u, float v)
{
    Vertex2 vert;
    vert.x = x;
    vert.y = y;
    vert.color = color;
    vert.depth = depth;
    vert.u = u;
    vert.v = v;
    m_vertices.push_back(vert);
}

bool Rasterizer::canSetPixel(int x, int y, float depth)
{
    if(depth < 0.f)
        return false;

    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    if(m_depthbuffer[x + y * 640] > depth)
        return true;

    return false;
}

void Rasterizer::setPixel(int x, int y, unsigned color, float depth)
{
    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    m_pixels[x + y * 640] = color;
    m_depthbuffer[x + y * 640] = depth;
}

unsigned Rasterizer::getTexel(float u, float v) const
{
    const int x = std::max(0, std::min<int>(round(u * m_texx), m_texx - 1));
    const int y = std::max(0, std::min<int>(round(v * m_texy), m_texy - 1));
    const unsigned char * tex = &m_texture[3 * (x + m_texx * y)];
    return (tex[0] << 16) + (tex[1] << 8) + tex[2];
}

void Rasterizer::toggleRenderMode()
{
    m_mode = (m_mode + 1) % ERENDER_MODE_COUNT;
}
<commit_msg>Added good pespective correct texturing.<commit_after>#include "Rasterizer.hpp"
#include <cmath>
#include <algorithm>
#include <float.h>
#include <cstdio>
#include <cassert>
#include "stb_image.h"

using std::modf;

Rasterizer::Rasterizer(void* pixels) :
m_pixels(static_cast<unsigned*>(pixels))
{
    int n;
    m_texture = stbi_load("texture.png", &m_texx, &m_texy, &n, 3);
    m_mode = ERM_TEXTURES;
}

Rasterizer::~Rasterizer()
{
    stbi_image_free(m_texture);
}

static inline float crossProduct(float ax, float ay, float bx, float by)
{
    return ax * by - ay * bx;
}

static inline int min(int a, int b, int c)
{
    return std::min(a, std::min(b, c));
}

static inline int max(int a, int b, int c)
{
    return std::max(a, std::max(b, c));
}

static inline void sepcolor(unsigned c, int& r, int& g, int& b)
{
    r = (c >> 16) & 0xff;
    g = (c >> 8) & 0xff;
    b = (c >> 0) & 0xff;
}

static inline unsigned mix3colors(unsigned c1, float v1, unsigned c2, float v2, unsigned c3, float v3)
{
    int r1, g1, b1;
    int r2, g2, b2;
    int r3, g3, b3;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    sepcolor(c3, r3, g3, b3);
    int rf = r1 * v1 + r2 * v2 + r3 * v3;
    int gf = g1 * v1 + g2 * v2 + g3 * v3;
    int bf = b1 * v1 + b2 * v2 + b3 * v3;
    return (rf << 16) + (gf << 8) + bf;
}

static inline unsigned mul2colors(unsigned c1, unsigned c2)
{
    int r1, g1, b1;
    int r2, g2, b2;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    int rf = (r1 * r2) / 255;
    int gf = (g1 * g2) / 255;
    int bf = (b1 * b2) / 255;
    assert(0 <= rf && rf <= 255);
    assert(0 <= gf && gf <= 255);
    assert(0 <= bf && bf <= 255);
    return (rf << 16) + (gf << 8) + bf;
}

static void adjustToView(int& x1, int& y1, int& x2, int& y2)
{
    x1 = std::max(0, std::min(x1, 640 - 1));
    y1 = std::max(0, std::min(y1, 480 - 1));
    x2 = std::max(0, std::min(x2, 640 - 1));
    y2 = std::max(0, std::min(y2, 480 - 1));
}

static unsigned rgbf(float r, float g, float b)
{
    const int rf = std::max(0, std::min<int>(255, r * 255.f));
    const int gf = std::max(0, std::min<int>(255, g * 255.f));
    const int bf = std::max(0, std::min<int>(255, b * 255.f));
    return (rf << 16) + (gf << 8) + bf;
}

static float normalizeTCoords(float x)
{
    float u;
    x = modf(x, &u);
    return std::fabs(x);
}

void Rasterizer::rasterize()
{
    for(int i = 0; i < 640 * 480; ++i)
        m_depthbuffer[i] = FLT_MAX;

    for(int i = 0; i < 640 * 480; ++i)
        m_pixels[i] = 0x202020; //very dark gray

    for(int i = 0; i < (int)m_vertices.size(); i += 3)
    {
        int x1 = m_vertices[i].x;
        int y1 = m_vertices[i].y;
        unsigned c1 = m_vertices[i].color;
        float d1 = m_vertices[i].depth;
        float u1 = m_vertices[i].u / d1;
        float v1 = m_vertices[i].v / d1;
        float d1i = 1.f / m_vertices[i].depth;

        int x2 = m_vertices[i + 1].x;
        int y2 = m_vertices[i + 1].y;
        unsigned c2 = m_vertices[i + 1].color;
        float d2 = m_vertices[i + 1].depth;
        float u2 = m_vertices[i + 1].u / d2;
        float v2 = m_vertices[i + 1].v / d2;
        float d2i = 1.f / m_vertices[i + 1].depth;

        int x3 = m_vertices[i + 2].x;
        int y3 = m_vertices[i + 2].y;
        unsigned c3 = m_vertices[i + 2].color;
        float d3 = m_vertices[i + 2].depth;
        float u3 = m_vertices[i + 2].u / d3;
        float v3 = m_vertices[i + 2].v / d3;
        float d3i = 1.f / m_vertices[i + 2].depth;

        //don't render triangles that might have been incorrectly
        //casted due to being behind the camera
        if(d1 < 0.f || d2 < 0.f || d3 < 0.f)
            continue;

        int maxX = max(x1, x2, x3);
        int minX = min(x1, x2, x3);
        int maxY = max(y1, y2, y3);
        int minY = min(y1, y2, y3);

        //clip
        adjustToView(minX, minY, maxX, maxY);

        for(int x = minX; x <= maxX; ++x)
        {
            for(int y = minY; y <= maxY; ++y)
            {
                const float w2 = crossProduct(x - x1, y - y1, x3 - x1, y3 - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                const float w3 = crossProduct(x2 - x1, y2 - y1, x - x1, y - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                if((w2 >= 0) && (w3 >= 0) && (w2 + w3 <= 1))
                {
                    const float w1 = 1.f - w2 - w3;
                    const float depth = d1 * w1 + d2 * w2 + d3 * w3;
                    const float depthi = d1i * w1 + d2i * w2 + d3i * w3;
                    if(canSetPixel(x, y, depth))
                    {
                        const unsigned color = mix3colors(c1, w1, c2, w2, c3, w3);
                        const float u = normalizeTCoords(u1 * w1 + u2 * w2 + u3 * w3);
                        const float v = normalizeTCoords(v1 * w1 + v2 * w2 + v3 * w3);
                        const unsigned texel = getTexel(u / depthi, v / depthi);
                        switch(m_mode)
                        {
                            case ERM_COLORS:
                                setPixel(x, y, color, depth);
                                break;
                            case ERM_TEXTURES:
                                setPixel(x, y, texel, depth);
                                break;
                            case ERM_COLORS_TEXTURES:
                                setPixel(x, y, mul2colors(color, texel), depth);
                                break;
                            case ERM_UV_RED_BLUE:
                                setPixel(x, y, rgbf(u, 0.f, v), depth);
                                break;
                        }//switch m_mode
                    }//can set pixel
                }//inside
            }//for y
        }//for x
    }//for each triangle
}

void Rasterizer::clear()
{
    m_vertices.clear();
}

void Rasterizer::addVertex(int x, int y, unsigned color, float depth, float u, float v)
{
    Vertex2 vert;
    vert.x = x;
    vert.y = y;
    vert.color = color;
    vert.depth = depth;
    vert.u = u;
    vert.v = v;
    m_vertices.push_back(vert);
}

bool Rasterizer::canSetPixel(int x, int y, float depth)
{
    if(depth < 0.f)
        return false;

    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    if(m_depthbuffer[x + y * 640] > depth)
        return true;

    return false;
}

void Rasterizer::setPixel(int x, int y, unsigned color, float depth)
{
    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    m_pixels[x + y * 640] = color;
    m_depthbuffer[x + y * 640] = depth;
}

unsigned Rasterizer::getTexel(float u, float v) const
{
    const int x = std::max(0, std::min<int>(round(u * m_texx), m_texx - 1));
    const int y = std::max(0, std::min<int>(round(v * m_texy), m_texy - 1));
    const unsigned char * tex = &m_texture[3 * (x + m_texx * y)];
    return (tex[0] << 16) + (tex[1] << 8) + tex[2];
}

void Rasterizer::toggleRenderMode()
{
    m_mode = (m_mode + 1) % ERENDER_MODE_COUNT;
}
<|endoftext|>


<commit_before>#include "SimpleIcon.h"
#include <graphics/IconPack.h>
#include <graphics/Painter.h>

namespace MGUI
{

ilixi::IconPack* SimpleIcon::__iconPack = NULL;

SimpleIcon::SimpleIcon(Widget* parent)
        : Widget(parent),
          _image(NULL)
{
    setConstraints(ilixi::FixedConstraint, ilixi::FixedConstraint);
    if (!__iconPack)
        __iconPack = new ilixi::IconPack(DATADIR"/theme/IconPack.xml");
}

SimpleIcon::~SimpleIcon()
{
    delete _image;
}

ilixi::Size
SimpleIcon::preferredSize() const
{
    return ilixi::Size(24, 24);
}

void
SimpleIcon::setImage(const std::string& name)
{
    if (_image)
        delete _image;
    _image = __iconPack->getIcon(name);
    update();
}

void
SimpleIcon::compose(const ilixi::PaintEvent& event)
{
    if (_image)
    {
        ilixi::Painter p(this);
        p.begin(event);
        p.drawImage(_image, 0, 0);
        p.end();
    }
}

} /* namespace MGUI */
<commit_msg>SimpleIcon: WakeUp main loop when image is set.<commit_after>#include "SimpleIcon.h"
#include <core/Engine.h>
#include <graphics/IconPack.h>
#include <graphics/Painter.h>

namespace MGUI
{

ilixi::IconPack* SimpleIcon::__iconPack = NULL;

SimpleIcon::SimpleIcon(Widget* parent)
        : Widget(parent),
          _image(NULL)
{
    setConstraints(ilixi::FixedConstraint, ilixi::FixedConstraint);
    if (!__iconPack)
        __iconPack = new ilixi::IconPack(DATADIR"/theme/IconPack.xml");
}

SimpleIcon::~SimpleIcon()
{
    delete _image;
}

ilixi::Size
SimpleIcon::preferredSize() const
{
    return ilixi::Size(24, 24);
}

void
SimpleIcon::setImage(const std::string& name)
{
    if (_image)
        delete _image;
    _image = __iconPack->getIcon(name);
    ilixi::Engine::instance().wakeUp();
    update();
}

void
SimpleIcon::compose(const ilixi::PaintEvent& event)
{
    if (_image)
    {
        ilixi::Painter p(this);
        p.begin(event);
        p.drawImage(_image, 0, 0);
        p.end();
    }
}

} /* namespace MGUI */
<|endoftext|>


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

#include "randomFunctionChecker.h"

#include <qrgui/plugins/pluginManager/editorManagerInterface.h>
#include <qrrepo/repoApi.h>
#include <qrtext/languageToolboxInterface.h>
#include <qrtext/lua/ast/functionCall.h>
#include <qrtext/lua/ast/identifier.h>

#include "parts/randomGeneratorPart.h"

using namespace pioneer::lua;

RandomFunctionChecker::RandomFunctionChecker(
		const qrRepo::RepoApi &repo
		, const qReal::EditorManagerInterface &metamodel
		, qrtext::LanguageToolboxInterface &languageToolbox
		, RandomGeneratorPart &randomGeneratorPart)
	: mRepo(repo)
	, mMetamodel(metamodel)
	, mLanguageToolbox(languageToolbox)
	, mRandomGeneratorPart(randomGeneratorPart)
{
}

void RandomFunctionChecker::checkNode(const qReal::Id &id)
{
	if (mRandomGeneratorPart.isUsed()) {
		// No point to do expensive AST walk if RNG will be initialized anyway.
		return;
	}

	const auto properties = mMetamodel.propertyNames(id.type());
	for (const auto &property : properties) {
		const auto ast = mLanguageToolbox.parse(id, property, mRepo.stringProperty(id, property));
		checkAst(ast);
	}
}

void RandomFunctionChecker::checkAst(QSharedPointer<qrtext::core::ast::Node> ast)
{
	if (ast->is<qrtext::lua::ast::FunctionCall>()) {
		auto call = qrtext::as<qrtext::lua::ast::FunctionCall>(ast);
		if (call->function()->is<qrtext::lua::ast::Identifier>()) {
			// We don't support indirect function calls here, but upstream text language tools do not support them
			// anyways.
			auto idNode = qrtext::as<qrtext::lua::ast::Identifier>(call->function());
			if (idNode->name() == "random") {
				mRandomGeneratorPart.registerUsage();
				return;
			}
		}
	}

	for (const auto child : ast->children()) {
		checkAst(child);
	}
}
<commit_msg>Fixed crash when there is a semantic error in property<commit_after>/* Copyright 2017 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "randomFunctionChecker.h"

#include <qrgui/plugins/pluginManager/editorManagerInterface.h>
#include <qrrepo/repoApi.h>
#include <qrtext/languageToolboxInterface.h>
#include <qrtext/lua/ast/functionCall.h>
#include <qrtext/lua/ast/identifier.h>

#include "parts/randomGeneratorPart.h"

using namespace pioneer::lua;

RandomFunctionChecker::RandomFunctionChecker(
		const qrRepo::RepoApi &repo
		, const qReal::EditorManagerInterface &metamodel
		, qrtext::LanguageToolboxInterface &languageToolbox
		, RandomGeneratorPart &randomGeneratorPart)
	: mRepo(repo)
	, mMetamodel(metamodel)
	, mLanguageToolbox(languageToolbox)
	, mRandomGeneratorPart(randomGeneratorPart)
{
}

void RandomFunctionChecker::checkNode(const qReal::Id &id)
{
	if (mRandomGeneratorPart.isUsed()) {
		// No point to do expensive AST walk if RNG will be initialized anyway.
		return;
	}

	const auto properties = mMetamodel.propertyNames(id.type());
	for (const auto &property : properties) {
		const auto ast = mLanguageToolbox.parse(id, property, mRepo.stringProperty(id, property));
		if (!ast.isNull()) {
			checkAst(ast);
		}
	}
}

void RandomFunctionChecker::checkAst(QSharedPointer<qrtext::core::ast::Node> ast)
{
	if (ast->is<qrtext::lua::ast::FunctionCall>()) {
		auto call = qrtext::as<qrtext::lua::ast::FunctionCall>(ast);
		if (call->function()->is<qrtext::lua::ast::Identifier>()) {
			// We don't support indirect function calls here, but upstream text language tools do not support them
			// anyways.
			auto idNode = qrtext::as<qrtext::lua::ast::Identifier>(call->function());
			if (idNode->name() == "random") {
				mRandomGeneratorPart.registerUsage();
				return;
			}
		}
	}

	for (const auto child : ast->children()) {
		checkAst(child);
	}
}
<|endoftext|>


<commit_before>/**
 * @file Transition.hpp
 * @author Duncan Campbell
 * @version 1.0
 *
 * @section LICENSE
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Duncan Campbell
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @section DESCRIPTION
 *
 * This class represents a transition from one state to another state.  A
 * transition is composed of a trigger and an action.  A trigger represents the
 * condition under which the trigger will activate.  An action will represent
 * the measures that are taken to transition over to the next state.
 */

#include <functional>

namespace StateTrans
{
    using Trigger = std::function<bool()>;
    using Action  = std::function<void()>;

    class Transition
    {
        public:
            Transition();
            Transition(Trigger, Action);
            ~Transition();

            bool CheckTrigger();
            void ExecuteAction();

            Trigger GetTrigger() const;
            void SetTrigger(const Trigger&);

            Action GetAction() const;
            void SetAction(const Action&);

        private:
            Trigger trigger;
            Action  action;
    };

} // end namespace
<commit_msg>Add in documentation for transitions<commit_after>/**
 * @file Transition.hpp
 * @author Duncan Campbell
 * @version 1.0
 *
 * @section LICENSE
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Duncan Campbell
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @section DESCRIPTION
 *
 * This class represents a transition from one state to another state.  A
 * transition is composed of a trigger and an action.  A trigger represents the
 * condition under which the trigger will activate.  An action will represent
 * the measures that are taken to transition over to the next state.
 */

#include <functional>

namespace StateTrans
{
    using Trigger = std::function<bool()>;
    using Action  = std::function<void()>;

    class Transition
    {
        public:
            /**
              * Constructor for Transitions that takes no arguments
              */
            Transition();

            /**
             * Constructor for Transitions that takes a Trigger and an Action
             *
             * @param trigger Trigger for the transition
             *
             * @param action Action for the Transitions
             */
            Transition(Trigger, Action);

            /**
             * Destructor for Transitions
             */
            ~Transition();

            /**
             * Checks the current state of the trigger for the Transition
             *
             * @return State of the Trigger
             */
            bool CheckTrigger();

            /**
             * Executes the action of the Transition
             */
            void ExecuteAction();

            /**
             * Get the Trigger for the Transition
             *
             * @return Trigger of the Transition
             */
            Trigger GetTrigger() const;

            /**
             * Set the Trigger for the Transition
             *
             * @param trigger Trigger to be set
             */
            void SetTrigger(const Trigger&);

            /**
             * Get the Action for the Transition
             *
             * @return Action of the Transition
             */
            Action GetAction() const;

            /**
             * Set the Action for the Transition
             *
             * @param action Action to be set
             */
            void SetAction(const Action&);

        private:
            Trigger trigger;
            Action  action;
    };

} // end namespace
<|endoftext|>


<commit_before>#include <OpenGLView.h>
#include <FWPlatformBase.h>
#include <Message.h>
#include <Logger.h>

#include <sstream>

#ifdef __APPLE__
#include <OpenGLES/ES3/gl.h>
#else
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

using namespace std;

void
OpenGLView::initialize(FWPlatformBase * _platform) {
  FWViewBase::initialize(_platform);
  sendMessage(Message(Message::CREATE_OPENGL_VIEW, getId()));
  logical_width = int(_platform->getDisplayWidth() / _platform->getDisplayScale());
  logical_height = int(_platform->getDisplayHeight() / _platform->getDisplayScale());
  actual_width = _platform->getDisplayWidth();
  actual_height = _platform->getDisplayHeight();
}

void
OpenGLView::checkGLError() {
  GLenum errLast = GL_NO_ERROR;
  for (;;) {
    GLenum err = glGetError();
    if (err == GL_NO_ERROR) {
      return;
    }

    // normally the error is reset by the call to glGetError() but if
    // glGetError() itself returns an error, we risk looping forever here
    // so check that we get a different error than the last time
    if (err == errLast) {
      getPlatform().getLogger().println("OpenGL error state couldn't be reset.");
      return;
    }

    errLast = err;

    ostringstream s;
    s << "got OpenGL error " << err;
    getPlatform().getLogger().println(s.str());
  }
}
<commit_msg>add parent id<commit_after>#include <OpenGLView.h>
#include <FWPlatformBase.h>
#include <Message.h>
#include <Logger.h>

#include <sstream>

#ifdef __APPLE__
#include <OpenGLES/ES3/gl.h>
#else
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

using namespace std;

void
OpenGLView::initialize(FWPlatformBase * _platform) {
  FWViewBase::initialize(_platform);
  sendMessage(Message(Message::CREATE_OPENGL_VIEW, getId(), getParentId()));
  logical_width = int(_platform->getDisplayWidth() / _platform->getDisplayScale());
  logical_height = int(_platform->getDisplayHeight() / _platform->getDisplayScale());
  actual_width = _platform->getDisplayWidth();
  actual_height = _platform->getDisplayHeight();
}

void
OpenGLView::checkGLError() {
  GLenum errLast = GL_NO_ERROR;
  for (;;) {
    GLenum err = glGetError();
    if (err == GL_NO_ERROR) {
      return;
    }

    // normally the error is reset by the call to glGetError() but if
    // glGetError() itself returns an error, we risk looping forever here
    // so check that we get a different error than the last time
    if (err == errLast) {
      getPlatform().getLogger().println("OpenGL error state couldn't be reset.");
      return;
    }

    errLast = err;

    ostringstream s;
    s << "got OpenGL error " << err;
    getPlatform().getLogger().println(s.str());
  }
}
<|endoftext|>


<commit_before>//
//  RealPlayer.cpp
//  SDL_Checkers
//
//  Created by Jacky Chiu on 2016-03-02.
//  Copyright © 2016 Jacky Chiu. All rights reserved.
//

#include "../include/RealPlayer.h"
#include "../include/GameState.h"

RealPlayer::RealPlayer(bool topSide, CheckersBoard *board, Button *buttons): Player(topSide, board, buttons){
    xLocation = 0, yLocation = 0;
    selectingState = false;
    currentPieceIndex = 0;
}

RealPlayer::~RealPlayer(){
    delete Board;
    Board = NULL;
    delete boardButtons;
    boardButtons = NULL;
}

bool RealPlayer::makeMove(SDL_Event* event){

    if (event->type == SDL_MOUSEBUTTONDOWN) {

        // Selecting state for inital piece //
        if (!selectingState) {
            for (int index=0; index<TOTAL_BUTTONS; index++) {
                if (boardButtons[index].insideButton(BUTTON_HEIGHT,BUTTON_WIDTH)) {
                    // Player selects a piece to move //
                    selectPiece(boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80);
                    break;
                }
            }
        }
        // Selecting for the piece to be moved //
        else{
            for (int index=0; index<TOTAL_BUTTONS; index++) {
                if (boardButtons[index].insideButton(BUTTON_HEIGHT,BUTTON_WIDTH)) {
                    //buttonIndex = index;
                    // Player selects where the piece should move //
                    if (selectedLocationIsValid(boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80)) {
                        movePiece(currentPieceIndex, boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80);
                        Board->turnHighLightOff();
                        return true;
                    }
                    else {
                        selectingState = false;
                        Board->turnHighLightOff();
                        return false;
                    }
                }
            }
        }
    }
    return false;
}

void RealPlayer::selectPiece(int x, int y){
    // SELECT PIECE //
    // When a piece hasn't been selected yet, and the button currently selected doesn't have a piece inside //
    switch (Board->virtualBoard[x][y]) {
        case EMPTY_PIECE:
            cout<<"Selected button isn't a piece"<<endl;
            break;
        case RED_PIECE:
            xLocation = x;
            yLocation = y;
            currentPieceIndex = pieceTeamIndexByXY(x, y);
            Board->turnHighLightOn(x, y);
            selectingState = true;
            cout << "Selected piece is:\t(" << x << ", " << y << ")" <<endl;
            break;
        case BLACK_PIECE:
            cout<<"Piece isn't apart of your team"<<endl;
            break;
        default:
            break;
    }
}

bool RealPlayer::selectedLocationIsValid(int x, int y) {
    cout << "Selected location is:\t(" << x << ", " << y << ")" <<endl;
    bool locationIsValid = false;
    // realPlayer select only works for (topside == false) //
    if (Board->virtualBoard[x][y] == EMPTY_PIECE) {

        // case 1: moving in a 3x3 square centered at the origin //
        if (abs(x - xLocation) == 1 && abs(y - yLocation) == 1) {

            // case 1.1: piece is a king //
            if (team[currentPieceIndex].isKing()) {
                locationIsValid = true;
            }

            // case 1.2: piece isn't a king //
            else if (yLocation - y == 1) {
                locationIsValid = true;
            }
        }

        // case 2: moving in a 5x5 square centered at the origin to kill a piece //
        else if (abs(x - xLocation) == 2 && abs(y - yLocation) == 2 && Board->virtualBoard[(x + xLocation)/2][(y + yLocation)/2] == BLACK_PIECE) {

            // case 2.1: piece is a king //
            if (team[currentPieceIndex].isKing()) {
                locationIsValid = true;
            }

            // case 2.2: piece isn't a king //
            else if (yLocation - y == 2) {
                locationIsValid = true;
            }
        }
    }
    // case 3: selects own piece to switch selection //
    else if(Board->virtualBoard[x][y] == RED_PIECE){
        selectPiece(x, y);
        locationIsValid = false;
    }
    if (!locationIsValid) {
        cout<<"cant move here"<<endl;
    }
    else{
        selectingState = false;
    }
    return locationIsValid;
}
<commit_msg>Fixed highlight not being activated when switched pieces<commit_after>//
//  RealPlayer.cpp
//  SDL_Checkers
//
//  Created by Jacky Chiu on 2016-03-02.
//  Copyright © 2016 Jacky Chiu. All rights reserved.
//

#include "../include/RealPlayer.h"
#include "../include/GameState.h"

RealPlayer::RealPlayer(bool topSide, CheckersBoard *board, Button *buttons): Player(topSide, board, buttons){
    xLocation = 0, yLocation = 0;
    selectingState = false;
    currentPieceIndex = 0;
}

RealPlayer::~RealPlayer(){
    delete Board;
    Board = NULL;
    delete boardButtons;
    boardButtons = NULL;
}

bool RealPlayer::makeMove(SDL_Event* event){

    if (event->type == SDL_MOUSEBUTTONDOWN) {

        // Selecting state for inital piece //
        if (!selectingState) {
            for (int index=0; index<TOTAL_BUTTONS; index++) {
                if (boardButtons[index].insideButton(BUTTON_HEIGHT,BUTTON_WIDTH)) {
                    // Player selects a piece to move //
                    selectPiece(boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80);
                    break;
                }
            }
        }
        // Selecting for the piece to be moved //
        else{
            for (int index=0; index<TOTAL_BUTTONS; index++) {
                if (boardButtons[index].insideButton(BUTTON_HEIGHT,BUTTON_WIDTH)) {
                    //buttonIndex = index;
                    // Player selects where the piece should move //
                    if (selectedLocationIsValid(boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80)) {
                        movePiece(currentPieceIndex, boardButtons[index].getButtonPointX()/80, boardButtons[index].getButtonPointY()/80);
                        Board->turnHighLightOff();
                        return true;
                    }
                    else {
                        selectingState = false;
                        return false;
                    }
                }
            }
        }
    }
    return false;
}

void RealPlayer::selectPiece(int x, int y){
    // SELECT PIECE //
    // When a piece hasn't been selected yet, and the button currently selected doesn't have a piece inside //
    switch (Board->virtualBoard[x][y]) {
        case EMPTY_PIECE:
            cout<<"Selected button isn't a piece"<<endl;
            break;
        case RED_PIECE:
            xLocation = x;
            yLocation = y;
            currentPieceIndex = pieceTeamIndexByXY(x, y);
            Board->turnHighLightOn(x, y);
            selectingState = true;
            cout << "Selected piece is:\t(" << x << ", " << y << ")" <<endl;
            break;
        case BLACK_PIECE:
            cout<<"Piece isn't apart of your team"<<endl;
            break;
        default:
            break;
    }
}

bool RealPlayer::selectedLocationIsValid(int x, int y) {
    cout << "Selected location is:\t(" << x << ", " << y << ")" <<endl;
    bool locationIsValid = false;
    // realPlayer select only works for (topside == false) //
    if (Board->virtualBoard[x][y] == EMPTY_PIECE) {

        // case 1: moving in a 3x3 square centered at the origin //
        if (abs(x - xLocation) == 1 && abs(y - yLocation) == 1) {

            // case 1.1: piece is a king //
            if (team[currentPieceIndex].isKing()) {
                locationIsValid = true;
            }

            // case 1.2: piece isn't a king //
            else if (yLocation - y == 1) {
                locationIsValid = true;
            }
        }

        // case 2: moving in a 5x5 square centered at the origin to kill a piece //
        else if (abs(x - xLocation) == 2 && abs(y - yLocation) == 2 && Board->virtualBoard[(x + xLocation)/2][(y + yLocation)/2] == BLACK_PIECE) {

            // case 2.1: piece is a king //
            if (team[currentPieceIndex].isKing()) {
                locationIsValid = true;
            }

            // case 2.2: piece isn't a king //
            else if (yLocation - y == 2) {
                locationIsValid = true;
            }
        }
    }
    // case 3: selects own piece to switch selection //
    else if(Board->virtualBoard[x][y] == RED_PIECE){
        selectPiece(x, y);
        locationIsValid = false;
    }
    if (!locationIsValid) {
        cout<<"cant move here"<<endl;
    }
    return locationIsValid;
}
<|endoftext|>


<commit_before>
#include <SerialComm.h>

#ifdef __AVR__
	#define PLATFORM_VSNPRINTF(...) vsnprintf_P(__VA_ARGS__)
#else
	#define PLATFORM_VSNPRINTF(...) vsnprintf(__VA_ARGS__)
#endif

SerialComm::SerialComm(Stream &s, int stream_buffer_size)
: m_serial(s)
, m_already_asked(false)
, m_stream_buffer_capacity(stream_buffer_size - 1)
//                                                                // Benchmark:
//                                                                // send a file of size 22846 bytes.
//, m_stream_buffer_threshold(m_stream_buffer_capacity)           //  6.41 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 15 / 16) //  6.21 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 14 / 16) //  6.18 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 13 / 16) //  6.13 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 12 / 16) //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 11 / 16) //  6.02 s
, m_stream_buffer_threshold(m_stream_buffer_capacity * 10 / 16)   //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  9 / 16) //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  8 / 16) //  6.03 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  7 / 16) //  6.03 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  6 / 16) //  6.04 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  5 / 16) //  6.06 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  4 / 16) //  6.07 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  3 / 16) //  6.11 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  2 / 16) //  6.17 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  1 / 16) //  6.37 s
//, m_stream_buffer_threshold(1)                                  // 22.81 s
, m_stream_buffer_checkpoint(0)
, m_stream_count(0)
{
	if (streamBufferThreshold() == 0) {
		setStreamBufferThreshold(streamBufferCapacity());
	}
	while (serial().available()) {
		serial().read();
	}
	Ready(F("XSVF"));
}

SerialComm::~SerialComm()
{
}

void SerialComm::ask_for_data()
{
	if (!alreadyAsked()) {
		checkAndRequestData(true);
		setAlreadyAsked();
	}
}

void SerialComm::Important(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);

	serial().print(F("!"));
	serial().println(formatBuffer());
}

void SerialComm::ImportantBits(const __FlashStringHelper *msg, const uint8_t *pb,
	uint32_t count_bits)
{
	uint32_t count_bytes = (count_bits + 7) >> 3;
	serial().print(msg);
	print_bytes(pb, count_bytes);
	serial().print(F("/"));
	serial().print(count_bits);
	serial().println(F(" bits"));
}

void SerialComm::checkAndRequestData(bool force)
{
	if (force ||
	    streamCount() % streamBufferCapacity() == streamBufferCheckpoint()) {
		updateCheckpoint();
		int n = force ? streamBufferCapacity() : streamBufferThreshold();
		snprintf(sendMsg(), sizeofSendMsg(), "S%-4d", n);
		serial().print(F("\r\n"));
		serial().println(sendMsg());
		if (DEBUG) {
			// Print this so that an interrupted line is
			// still recognized by the python script.
			serial().print(F("D.   >>>   "));
		}
	}
}

int SerialComm::nextByte()
{
	// Wait for TIMEOUT milliseconds if the buffer is empty.
	//unsigned const int TIMEOUT = 1000; // milliseconds
	unsigned const int TIMEOUT = 3000; // milliseconds
	unsigned long end_time = millis() + TIMEOUT;
        while (serial().available() <= 0 && millis() < end_time) {
        }
        // Return an invalid instruction
	int c = -1;
	int n = serial().available();
	if (n > 0) {
		c = serial().read();
		incStreamCount();
		checkAndRequestData();
	} else {
		Important(F("count: %ld, threshold: %d, mod: %ld, avail: %d"),
			streamCount(), streamBufferThreshold(),
			streamCount() % streamBufferCapacity(),
			n);
	}

	return c;
}

// Not needed, left here as example.
#if 0
void SerialComm::CopyToFlashBuffer(const __FlashStringHelper *ifsh)
{
	PGM_P p = reinterpret_cast<PGM_P>(ifsh);
	// Truncate message to the flash buffer size
	strncpy_P(flashBuffer(), p, S_FLASH_BUFFER_SIZE);

	// Left here as example of use of pgm_read_byte().
	/*
	char *s = flashBuffer();
	char c;
	uint32_t n = S_FLASH_BUFFER_SIZE;
	while (n-- && (c = pgm_read_byte(p++))) {
		*s++ = c;
	}
	if (n) {
		*s = 0;
	} else {
		*--s = 0;
	}
	*/
}
#endif

#if DEBUG == 1

void SerialComm::DebugStartMessage() const
{
	serial().print(F("D"));
}

void SerialComm::DebugContMessage(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);
	serial().print(formatBuffer());
}

void SerialComm::Debug(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);
	DebugStartMessage();
	serial().println(formatBuffer());
}

void SerialComm::DebugBytes(const __FlashStringHelper *s, const uint8_t *b,
	uint8_t n)
{
	DebugStartMessage();
	serial().print(s);
	print_bytes(b, n);
	serial().println();
}

#else

void SerialComm::DebugStartMessage() const {}
void SerialComm::DebugContMessage(const __FlashStringHelper *ifsh, ...) {}
void SerialComm::Debug(const __FlashStringHelper *fmt, ...) {}
void SerialComm::DebugBytes(const __FlashStringHelper *s, const uint8_t* p, uint8_t n) {}

#endif

void SerialComm::Ready(const __FlashStringHelper *message) const
{
	serial().print(F("\r\nR"));
	serial().println(message);
}

void SerialComm::Quit(int error_code, const __FlashStringHelper *message) const
{
	serial().print(F("\r\nQ"));
	serial().print(error_code);
	serial().print(F(","));
	serial().println(message);
}

void SerialComm::print_bytes(const uint8_t *pb, uint32_t count, bool lf)
{
	const unsigned char *p = reinterpret_cast<const unsigned char *>(pb);
	char *fmt_msg = " %02X";
	int fmt_msg_size = 3;
	while (count) {
		char *f = formatBuffer();
		int buf_size = S_FORMAT_BUFFER_SIZE;
		while (count && buf_size > 6) {
			snprintf(f, buf_size, fmt_msg, *p);
			p++;
			f += fmt_msg_size;
			buf_size -= fmt_msg_size;
			count--;
		}
		if (count && buf_size <= 6) {
			serial().print(formatBuffer());
		}
	}
	if (lf) {
		serial().println(formatBuffer());
	} else {
		serial().print(formatBuffer());
	}
}

<commit_msg>Fix a bug when printing a zero bits sequence<commit_after>
#include <SerialComm.h>

#ifdef __AVR__
	#define PLATFORM_VSNPRINTF(...) vsnprintf_P(__VA_ARGS__)
#else
	#define PLATFORM_VSNPRINTF(...) vsnprintf(__VA_ARGS__)
#endif

SerialComm::SerialComm(Stream &s, int stream_buffer_size)
: m_serial(s)
, m_already_asked(false)
, m_stream_buffer_capacity(stream_buffer_size - 1)
//                                                                // Benchmark:
//                                                                // send a file of size 22846 bytes.
//, m_stream_buffer_threshold(m_stream_buffer_capacity)           //  6.41 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 15 / 16) //  6.21 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 14 / 16) //  6.18 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 13 / 16) //  6.13 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 12 / 16) //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity * 11 / 16) //  6.02 s
, m_stream_buffer_threshold(m_stream_buffer_capacity * 10 / 16)   //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  9 / 16) //  6.02 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  8 / 16) //  6.03 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  7 / 16) //  6.03 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  6 / 16) //  6.04 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  5 / 16) //  6.06 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  4 / 16) //  6.07 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  3 / 16) //  6.11 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  2 / 16) //  6.17 s
//, m_stream_buffer_threshold(m_stream_buffer_capacity *  1 / 16) //  6.37 s
//, m_stream_buffer_threshold(1)                                  // 22.81 s
, m_stream_buffer_checkpoint(0)
, m_stream_count(0)
{
	if (streamBufferThreshold() == 0) {
		setStreamBufferThreshold(streamBufferCapacity());
	}
	while (serial().available()) {
		serial().read();
	}
	Ready(F("XSVF"));
}

SerialComm::~SerialComm()
{
}

void SerialComm::ask_for_data()
{
	if (!alreadyAsked()) {
		checkAndRequestData(true);
		setAlreadyAsked();
	}
}

void SerialComm::Important(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);

	serial().print(F("!"));
	serial().println(formatBuffer());
}

void SerialComm::ImportantBits(const __FlashStringHelper *msg, const uint8_t *pb,
	uint32_t count_bits)
{
	uint32_t count_bytes = (count_bits + 7) >> 3;
	serial().print(msg);
	print_bytes(pb, count_bytes);
	serial().print(F("/"));
	serial().print(count_bits);
	serial().println(F(" bits"));
}

void SerialComm::checkAndRequestData(bool force)
{
	if (force ||
	    streamCount() % streamBufferCapacity() == streamBufferCheckpoint()) {
		updateCheckpoint();
		int n = force ? streamBufferCapacity() : streamBufferThreshold();
		snprintf(sendMsg(), sizeofSendMsg(), "S%-4d", n);
		serial().print(F("\r\n"));
		serial().println(sendMsg());
		if (DEBUG) {
			// Print this so that an interrupted line is
			// still recognized by the python script.
			serial().print(F("D.   >>>   "));
		}
	}
}

int SerialComm::nextByte()
{
	// Wait for TIMEOUT milliseconds if the buffer is empty.
	//unsigned const int TIMEOUT = 1000; // milliseconds
	unsigned const int TIMEOUT = 3000; // milliseconds
	unsigned long end_time = millis() + TIMEOUT;
        while (serial().available() <= 0 && millis() < end_time) {
        }
        // Return an invalid instruction
	int c = -1;
	int n = serial().available();
	if (n > 0) {
		c = serial().read();
		incStreamCount();
		checkAndRequestData();
	} else {
		Important(F("count: %ld, threshold: %d, mod: %ld, avail: %d"),
			streamCount(), streamBufferThreshold(),
			streamCount() % streamBufferCapacity(),
			n);
	}

	return c;
}

// Not needed, left here as example.
#if 0
void SerialComm::CopyToFlashBuffer(const __FlashStringHelper *ifsh)
{
	PGM_P p = reinterpret_cast<PGM_P>(ifsh);
	// Truncate message to the flash buffer size
	strncpy_P(flashBuffer(), p, S_FLASH_BUFFER_SIZE);

	// Left here as example of use of pgm_read_byte().
	/*
	char *s = flashBuffer();
	char c;
	uint32_t n = S_FLASH_BUFFER_SIZE;
	while (n-- && (c = pgm_read_byte(p++))) {
		*s++ = c;
	}
	if (n) {
		*s = 0;
	} else {
		*--s = 0;
	}
	*/
}
#endif

#if DEBUG == 1

void SerialComm::DebugStartMessage() const
{
	serial().print(F("D"));
}

void SerialComm::DebugContMessage(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);
	serial().print(formatBuffer());
}

void SerialComm::Debug(const __FlashStringHelper *ifsh, ...)
{
	va_list args;
	va_start(args, ifsh);
	PLATFORM_VSNPRINTF(formatBuffer(), S_FORMAT_BUFFER_SIZE,
		(const char *)ifsh, args);
	va_end(args);
	DebugStartMessage();
	serial().println(formatBuffer());
}

void SerialComm::DebugBytes(const __FlashStringHelper *s, const uint8_t *b,
	uint8_t n)
{
	DebugStartMessage();
	serial().print(s);
	print_bytes(b, n);
	serial().println();
}

#else

void SerialComm::DebugStartMessage() const {}
void SerialComm::DebugContMessage(const __FlashStringHelper *ifsh, ...) {}
void SerialComm::Debug(const __FlashStringHelper *fmt, ...) {}
void SerialComm::DebugBytes(const __FlashStringHelper *s, const uint8_t* p, uint8_t n) {}

#endif

void SerialComm::Ready(const __FlashStringHelper *message) const
{
	serial().print(F("\r\nR"));
	serial().println(message);
}

void SerialComm::Quit(int error_code, const __FlashStringHelper *message) const
{
	serial().print(F("\r\nQ"));
	serial().print(error_code);
	serial().print(F(","));
	serial().println(message);
}

void SerialComm::print_bytes(const uint8_t *pb, uint32_t count, bool lf)
{
	if (!count) {
		if (lf) {
			serial().println(F(" "));
		} else {
			serial().print(F(" "));
		}
		return;
	}
	const unsigned char *p = reinterpret_cast<const unsigned char *>(pb);
	char *fmt_msg = " %02X";
	int fmt_msg_size = 3;
	while (count) {
		char *f = formatBuffer();
		int buf_size = S_FORMAT_BUFFER_SIZE;
		while (count && buf_size > 6) {
			snprintf(f, buf_size, fmt_msg, *p);
			p++;
			f += fmt_msg_size;
			buf_size -= fmt_msg_size;
			count--;
		}
		if (count && buf_size <= 6) {
			serial().print(formatBuffer());
		}
	}
	if (lf) {
		serial().println(formatBuffer());
	} else {
		serial().print(formatBuffer());
	}
}

<|endoftext|>


<commit_before>#include <sstream>

#include <eosio/chain/block_log.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/snapshot.hpp>
#include <eosio/testing/tester.hpp>

#include <boost/mpl/list.hpp>
#include <boost/test/unit_test.hpp>

#include <contracts.hpp>
#include <snapshots.hpp>

using namespace eosio;
using namespace testing;
using namespace chain;

void remove_existing_blocks(controller::config& config) {
   auto block_log_path = config.blocks_dir / "blocks.log";
   remove(block_log_path);
   auto block_index_path = config.blocks_dir / "blocks.index";
   remove(block_index_path);
}

BOOST_AUTO_TEST_SUITE(restart_chain_tests)

BOOST_AUTO_TEST_CASE(test_existing_state_without_block_log)
{
   tester chain;

   chain.create_account(N(snapshot));
   std::vector<signed_block_ptr> blocks;
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());

   tester other;
   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
   blocks.clear();

   other.close();
   auto cfg = other.get_config();
   remove_existing_blocks(cfg);
   // restarting chain with no block log and no genesis
   other.open();

   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   chain.control->abort_block();

   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
}

BOOST_AUTO_TEST_CASE(test_restart_with_different_chain_id)
{
   tester chain;

   chain.create_account(N(snapshot));
   std::vector<signed_block_ptr> blocks;
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());

   tester other;
   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
   blocks.clear();

   other.close();
   genesis_state genesis;
   genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.999");
   genesis.initial_key = eosio::testing::base_tester::get_public_key( config::system_account_name, "active" );
   fc::optional<chain_id_type> chain_id = genesis.compute_chain_id();
   BOOST_REQUIRE_EXCEPTION(other.open(chain_id), block_log_exception, fc_exception_message_starts_with("Controller configured with: "));
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fixed expected exception.<commit_after>#include <sstream>

#include <eosio/chain/block_log.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/snapshot.hpp>
#include <eosio/testing/tester.hpp>

#include <boost/mpl/list.hpp>
#include <boost/test/unit_test.hpp>

#include <contracts.hpp>
#include <snapshots.hpp>

using namespace eosio;
using namespace testing;
using namespace chain;

void remove_existing_blocks(controller::config& config) {
   auto block_log_path = config.blocks_dir / "blocks.log";
   remove(block_log_path);
   auto block_index_path = config.blocks_dir / "blocks.index";
   remove(block_index_path);
}

BOOST_AUTO_TEST_SUITE(restart_chain_tests)

BOOST_AUTO_TEST_CASE(test_existing_state_without_block_log)
{
   tester chain;

   chain.create_account(N(snapshot));
   std::vector<signed_block_ptr> blocks;
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());

   tester other;
   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
   blocks.clear();

   other.close();
   auto cfg = other.get_config();
   remove_existing_blocks(cfg);
   // restarting chain with no block log and no genesis
   other.open();

   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   chain.control->abort_block();

   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
}

BOOST_AUTO_TEST_CASE(test_restart_with_different_chain_id)
{
   tester chain;

   chain.create_account(N(snapshot));
   std::vector<signed_block_ptr> blocks;
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());
   blocks.push_back(chain.produce_block());

   tester other;
   for (auto new_block : blocks) {
      other.push_block(new_block);
   }
   blocks.clear();

   other.close();
   genesis_state genesis;
   genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.999");
   genesis.initial_key = eosio::testing::base_tester::get_public_key( config::system_account_name, "active" );
   fc::optional<chain_id_type> chain_id = genesis.compute_chain_id();
   BOOST_REQUIRE_EXCEPTION(other.open(chain_id), chain_id_type_exception, fc_exception_message_starts_with("chain ID in state "));
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>
#include <QApplication>
#include <QKeyEvent>
#include <QPushButton>
#include "GLModelViewer.h"
#include "GLModel.h"
#include "GLShaderProgram.h"
#include "Grid.h"
#include <iostream>
#include <chrono>
#include <sstream>
#include <fstream>
#include <Eigen/Dense>
#include "Timer.h"
#include "Projection.h"
#include "Volumetric_helper.h"

#if 0
void raycast_volume()
{
	timer.start();

	Eigen::Vector3d origin = T.first.col(3).head<3>();
	Eigen::Vector3d window_coord_norm;

	std::vector<Eigen::Vector3d> output_cloud;

	// Sweep the volume looking for the zero crossing
	for (int y = 0; y < window_height * 0.1; ++y)
	{
		std::cout << "Ray casting to image... " << (double)y / window_height * 100 << "%" << std::endl;

		for (int x = 0; x < window_width * 0.1; ++x)
		{
			window_coord_norm.x() = ((double)x / window_width * 2.0) - 1.0;
			window_coord_norm.y() = ((double)y / window_height * 2.0) - 1.0;
			window_coord_norm.z() = origin.z() + near_plane;
			Eigen::Vector3d direction = (window_coord_norm - origin).normalized();

			std::vector<int> intersections = Grid::find_intersections(grid.data, volume_size, voxel_size, grid.transformation, origin, direction, near_plane, far_plane);
			Grid::sort_intersections(intersections, grid.data, origin);

			for (int i = 1; i < intersections.size(); ++i)
			{
				const Voxeld& prev = grid.data.at(i - 1);
				const Voxeld& curr = grid.data.at(i);

				const bool& same_sign = ((prev.tsdf < 0) == (curr.tsdf < 0));

				if (!same_sign)		// it is a zero-crossing
				{
					output_cloud.push_back(curr.point);
				}
			}
		}
	}

	timer.print_interval("Raycasting volume   : ");

	export_obj("../../data/output_cloud.obj", output_cloud);
}
#endif

// Usage: ./Volumetricd.exe ../../data/plane.obj 256 8 2 90
int main(int argc, char **argv)
{
	if (argc < 6)
	{
		std::cerr << "Missing parameters. Abort."
			<< std::endl
			<< "Usage:  ./Volumetricd.exe ../../data/monkey.obj 256 8 2 90"
			<< std::endl;
		return EXIT_FAILURE;
	}
	Timer timer;
	const std::string filepath = argv[1];
	const int vol_size = atoi(argv[2]);
	const int vx_size = atoi(argv[3]);
	const int cloud_count = atoi(argv[4]);
	const int rot_interval = atoi(argv[5]);

	std::pair<std::vector<double>, std::vector<double>> depth_buffer;

	//
	// Projection and Modelview Matrices
	//
	Eigen::Matrix4d K = perspective_matrix(fov_y, aspect_ratio, near_plane, far_plane);
	std::pair<Eigen::Matrix4d, Eigen::Matrix4d>	T(Eigen::Matrix4d::Identity(), Eigen::Matrix4d::Identity());

	//
	// Creating volume
	//
	Eigen::Vector3d voxel_size(vx_size, vx_size, vx_size);
	Eigen::Vector3d volume_size(vol_size, vol_size, vol_size);
	Eigen::Vector3d voxel_count(volume_size.x() / voxel_size.x(), volume_size.y() / voxel_size.y(), volume_size.z() / voxel_size.z());
	//
	Eigen::Affine3d grid_affine = Eigen::Affine3d::Identity();
	grid_affine.translate(Eigen::Vector3d(0, 0, -256));
	grid_affine.scale(Eigen::Vector3d(1, 1, -1));	// z is negative inside of screen
#if 0
	Grid grid(volume_size, voxel_size, grid_affine.matrix());

	//
	// Importing .obj
	//
	timer.start();
	std::vector<Eigen::Vector3d> points3DOrig, pointsTmp;
	import_obj(filepath, points3DOrig);
	timer.print_interval("Importing monkey    : ");
	std::cout << "Monkey point count  : " << points3DOrig.size() << std::endl;

	//
	// Translating and rotating monkey point cloud
	std::pair<std::vector<Eigen::Vector3d>, std::vector<Eigen::Vector3d>> cloud;
	//
	Eigen::Affine3d rotate = Eigen::Affine3d::Identity();
	Eigen::Affine3d translate = Eigen::Affine3d::Identity();
	translate.translate(Eigen::Vector3d(0, 0, -256));

	//
	// Compute first cloud
	//
	for (Eigen::Vector3d p3d : points3DOrig)
	{
		Eigen::Vector4d rot = translate.matrix() * rotate.matrix() * p3d.homogeneous();
		rot /= rot.w();
		cloud.first.push_back(rot.head<3>());
	}
	//
	// Update grid with first cloud
	//
	timer.start();
	create_depth_buffer(depth_buffer.first, cloud.first, K, Eigen::Matrix4d::Identity(), far_plane);
	timer.print_interval("CPU compute depth   : ");

	timer.start();
	update_volume(grid, depth_buffer.first, K, T.first);
	timer.print_interval("CPU Update volume   : ");

	//
	// Compute next clouds
	Eigen::Matrix4d cloud_mat = Eigen::Matrix4d::Identity();
	Timer iter_timer;
	for (int i = 1; i < cloud_count; ++i)
	{
		std::cout << std::endl << i << " : " << i * rot_interval << std::endl;
		iter_timer.start();

		// Rotation matrix
		rotate = Eigen::Affine3d::Identity();
		rotate.rotate(Eigen::AngleAxisd(DegToRad(i * rot_interval), Eigen::Vector3d::UnitY()));

		cloud.second.clear();
		for (Eigen::Vector3d p3d : points3DOrig)
		{
			Eigen::Vector4d rot = translate.matrix() * rotate.matrix() * p3d.homogeneous();
			rot /= rot.w();
			cloud.second.push_back(rot.head<3>());
		}

		//export_obj("../../data/cloud_cpu_2.obj", cloud.second);

		timer.start();
		create_depth_buffer(depth_buffer.second, cloud.second, K, Eigen::Matrix4d::Identity(), far_plane);
		timer.print_interval("Compute depth buffer: ");

		//export_depth_buffer("../../data/cpu_depth_buffer_2.obj", depth_buffer.second);

		timer.start();
		Eigen::Matrix4d icp_mat;
		ComputeRigidTransform(cloud.first, cloud.second, icp_mat);
		timer.print_interval("Compute rigid transf: ");

		//std::cout << std::fixed << std::endl << "icp_mat " << std::endl << icp_mat << std::endl;

		// accumulate matrix
		cloud_mat = cloud_mat * icp_mat;

		//std::cout << std::fixed << std::endl << "cloud_mat " << std::endl << cloud_mat << std::endl;

		timer.start();
		//update_volume(grid, depth_buffer.second, K, cloud_mat.inverse());
		update_volume(grid, depth_buffer.second, K, cloud_mat.inverse());
		timer.print_interval("Update volume       : ");

		// copy second point cloud to first
		cloud.first = cloud.second;
		//depth_buffer.first = depth_buffer.second;

		iter_timer.print_interval("Iteration time      : ");
	}

	//std::cout << "------- // --------" << std::endl;
	//for (int i = 0; i <  grid.data.size(); ++i)
	//{
	//	const Eigen::Vector3d& point = grid.data[i].point;

	//	std::cout << point.transpose() << "\t\t" << grid.data[i].tsdf << " " << grid.data[i].weight << std::endl;
	//}
	//std::cout << "------- // --------" << std::endl;

	timer.start();
	export_volume("../../data/grid_volume_cpu.obj", grid.data);
	timer.print_interval("Exporting volume    : ");
#endif

	QApplication app(argc, argv);

#if 0

	//
	// setup opengl viewer
	//
	GLModelViewer glwidget;
	glwidget.resize(640, 480);
	glwidget.setPerspective(60.0f, 0.1f, 1024.0f);
	glwidget.move(320, 0);
	glwidget.setWindowTitle("Point Cloud");
	glwidget.setWeelSpeed(0.1f);
	glwidget.setDistance(-0.5f);
	glwidget.show();

	timer.start();
	std::vector<Eigen::Vector4f> points3DOrig;
	import_obj(filepath, points3DOrig);
	timer.print_interval("Importing monkey    : ");
	std::cout << "Monkey point count  : " << points3DOrig.size() << std::endl;

	//
	// setup model
	//
	std::shared_ptr<GLModel> cloud(new GLModel);
	cloud->initGL();
	cloud->setVertices(&points3DOrig[0][0], points3DOrig.size(), 4);
	cloud->setNormals(&points3DOrig[0][0], points3DOrig.size(), 4);
	cloud->transform().rotate(180, 0, 1, 0);
	glwidget.addModel(cloud);

	//
	// setup kinect shader program
	//
	std::shared_ptr<GLShaderProgram> kinectShaderProgram(new GLShaderProgram);
	if (kinectShaderProgram->build("color.vert", "color.frag"))
		cloud->setShaderProgram(kinectShaderProgram);

#else

	//
	// setup opengl viewer
	//
	GLModelViewer glwidget;
	glwidget.resize(640, 480);
	glwidget.setPerspective(60.0f, 0.1f, 1024.0f);
	glwidget.move(320, 0);
	glwidget.setWindowTitle("Point Cloud");
	glwidget.setWeelSpeed(0.1f);
	glwidget.setDistance(-0.5f);
	glwidget.show();

	Eigen::Matrix4d to_origin = Eigen::Matrix4d::Identity();
	to_origin.col(3) << -(volume_size.x() / 2.0), -(volume_size.y() / 2.0), -(volume_size.z() / 2.0), 1.0;	// set translate

	std::vector<Eigen::Vector4f> vertices, colors;

	int i = 0;
	for (int z = 0; z <= volume_size.z(); z += voxel_size.z())
	{
		for (int y = 0; y <= volume_size.y(); y += voxel_size.y())
		{
			for (int x = 0; x <= volume_size.x(); x += voxel_size.x(), i++)
			{
				Eigen::Vector4d p = grid_affine.matrix() * to_origin * Eigen::Vector4d(x, y, z, 1);
				p /= p.w();
				vertices.push_back(p.cast<float>());

				colors.push_back(Eigen::Vector4f(1, 1, 0, 1));
			}
		}
	}

	//
	// setup model
	//
	std::shared_ptr<GLModel> model(new GLModel);
	model->initGL();
	model->setVertices(&vertices[0][0], vertices.size(), 4);
	model->setColors(&colors[0][0], colors.size(), 4);
	glwidget.addModel(model);

	//
	// setup kinect shader program
	//
	std::shared_ptr<GLShaderProgram> kinectShaderProgram(new GLShaderProgram);
	if (kinectShaderProgram->build("color.vert", "color.frag"))
		model->setShaderProgram(kinectShaderProgram);

#endif

	return app.exec();
}

<commit_msg>Viewing grid on screen<commit_after>
#include <QApplication>
#include <QKeyEvent>
#include <QPushButton>
#include "GLModelViewer.h"
#include "GLModel.h"
#include "GLShaderProgram.h"
#include "Grid.h"
#include <iostream>
#include <chrono>
#include <sstream>
#include <fstream>
#include <Eigen/Dense>
#include "Timer.h"
#include "Projection.h"
#include "Volumetric_helper.h"

#if 0
void raycast_volume()
{
	timer.start();

	Eigen::Vector3d origin = T.first.col(3).head<3>();
	Eigen::Vector3d window_coord_norm;

	std::vector<Eigen::Vector3d> output_cloud;

	// Sweep the volume looking for the zero crossing
	for (int y = 0; y < window_height * 0.1; ++y)
	{
		std::cout << "Ray casting to image... " << (double)y / window_height * 100 << "%" << std::endl;

		for (int x = 0; x < window_width * 0.1; ++x)
		{
			window_coord_norm.x() = ((double)x / window_width * 2.0) - 1.0;
			window_coord_norm.y() = ((double)y / window_height * 2.0) - 1.0;
			window_coord_norm.z() = origin.z() + near_plane;
			Eigen::Vector3d direction = (window_coord_norm - origin).normalized();

			std::vector<int> intersections = Grid::find_intersections(grid.data, volume_size, voxel_size, grid.transformation, origin, direction, near_plane, far_plane);
			Grid::sort_intersections(intersections, grid.data, origin);

			for (int i = 1; i < intersections.size(); ++i)
			{
				const Voxeld& prev = grid.data.at(i - 1);
				const Voxeld& curr = grid.data.at(i);

				const bool& same_sign = ((prev.tsdf < 0) == (curr.tsdf < 0));

				if (!same_sign)		// it is a zero-crossing
				{
					output_cloud.push_back(curr.point);
				}
			}
		}
	}

	timer.print_interval("Raycasting volume   : ");

	export_obj("../../data/output_cloud.obj", output_cloud);
}
#endif

// Usage: ./Volumetricd.exe ../../data/plane.obj 256 8 2 90
int main(int argc, char **argv)
{
	if (argc < 6)
	{
		std::cerr << "Missing parameters. Abort."
			<< std::endl
			<< "Usage:  ./Volumetricd.exe ../../data/monkey.obj 256 8 2 90"
			<< std::endl;
		return EXIT_FAILURE;
	}
	Timer timer;
	const std::string filepath = argv[1];
	const int vol_size = atoi(argv[2]);
	const int vx_size = atoi(argv[3]);
	const int cloud_count = atoi(argv[4]);
	const int rot_interval = atoi(argv[5]);

	std::pair<std::vector<double>, std::vector<double>> depth_buffer;

	//
	// Projection and Modelview Matrices
	//
	Eigen::Matrix4d K = perspective_matrix(fov_y, aspect_ratio, near_plane, far_plane);
	std::pair<Eigen::Matrix4d, Eigen::Matrix4d>	T(Eigen::Matrix4d::Identity(), Eigen::Matrix4d::Identity());

	//
	// Creating volume
	//
	Eigen::Vector3d voxel_size(vx_size, vx_size, vx_size);
	Eigen::Vector3d volume_size(vol_size, vol_size, vol_size);
	Eigen::Vector3d voxel_count(volume_size.x() / voxel_size.x(), volume_size.y() / voxel_size.y(), volume_size.z() / voxel_size.z());
	//
	Eigen::Affine3d grid_affine = Eigen::Affine3d::Identity();
	grid_affine.translate(Eigen::Vector3d(0, 0, -256));
	grid_affine.scale(Eigen::Vector3d(1, 1, -1));	// z is negative inside of screen

	Grid grid(volume_size, voxel_size, grid_affine.matrix());

	//
	// Importing .obj
	//
	timer.start();
	std::vector<Eigen::Vector3d> points3DOrig, pointsTmp;
	import_obj(filepath, points3DOrig);
	timer.print_interval("Importing monkey    : ");
	std::cout << "Monkey point count  : " << points3DOrig.size() << std::endl;

	//
	// Translating and rotating monkey point cloud
	std::pair<std::vector<Eigen::Vector3d>, std::vector<Eigen::Vector3d>> cloud;
	//
	Eigen::Affine3d rotate = Eigen::Affine3d::Identity();
	Eigen::Affine3d translate = Eigen::Affine3d::Identity();
	translate.translate(Eigen::Vector3d(0, 0, -256));

	//
	// Compute first cloud
	//
	for (Eigen::Vector3d p3d : points3DOrig)
	{
		Eigen::Vector4d rot = translate.matrix() * rotate.matrix() * p3d.homogeneous();
		rot /= rot.w();
		cloud.first.push_back(rot.head<3>());
	}
	//
	// Update grid with first cloud
	//
	timer.start();
	create_depth_buffer(depth_buffer.first, cloud.first, K, Eigen::Matrix4d::Identity(), far_plane);
	timer.print_interval("CPU compute depth   : ");

	timer.start();
	update_volume(grid, depth_buffer.first, K, T.first);
	timer.print_interval("CPU Update volume   : ");

	//
	// Compute next clouds
	Eigen::Matrix4d cloud_mat = Eigen::Matrix4d::Identity();
	Timer iter_timer;
	for (int i = 1; i < cloud_count; ++i)
	{
		std::cout << std::endl << i << " : " << i * rot_interval << std::endl;
		iter_timer.start();

		// Rotation matrix
		rotate = Eigen::Affine3d::Identity();
		rotate.rotate(Eigen::AngleAxisd(DegToRad(i * rot_interval), Eigen::Vector3d::UnitY()));

		cloud.second.clear();
		for (Eigen::Vector3d p3d : points3DOrig)
		{
			Eigen::Vector4d rot = translate.matrix() * rotate.matrix() * p3d.homogeneous();
			rot /= rot.w();
			cloud.second.push_back(rot.head<3>());
		}

		//export_obj("../../data/cloud_cpu_2.obj", cloud.second);

		timer.start();
		create_depth_buffer(depth_buffer.second, cloud.second, K, Eigen::Matrix4d::Identity(), far_plane);
		timer.print_interval("Compute depth buffer: ");

		//export_depth_buffer("../../data/cpu_depth_buffer_2.obj", depth_buffer.second);

		timer.start();
		Eigen::Matrix4d icp_mat;
		ComputeRigidTransform(cloud.first, cloud.second, icp_mat);
		timer.print_interval("Compute rigid transf: ");

		//std::cout << std::fixed << std::endl << "icp_mat " << std::endl << icp_mat << std::endl;

		// accumulate matrix
		cloud_mat = cloud_mat * icp_mat;

		//std::cout << std::fixed << std::endl << "cloud_mat " << std::endl << cloud_mat << std::endl;

		timer.start();
		//update_volume(grid, depth_buffer.second, K, cloud_mat.inverse());
		update_volume(grid, depth_buffer.second, K, cloud_mat.inverse());
		timer.print_interval("Update volume       : ");

		// copy second point cloud to first
		cloud.first = cloud.second;
		//depth_buffer.first = depth_buffer.second;

		iter_timer.print_interval("Iteration time      : ");
	}

	//std::cout << "------- // --------" << std::endl;
	//for (int i = 0; i <  grid.data.size(); ++i)
	//{
	//	const Eigen::Vector3d& point = grid.data[i].point;

	//	std::cout << point.transpose() << "\t\t" << grid.data[i].tsdf << " " << grid.data[i].weight << std::endl;
	//}
	//std::cout << "------- // --------" << std::endl;

//	timer.start();
//	export_volume("../../data/grid_volume_cpu.obj", grid.data);
//	timer.print_interval("Exporting volume    : ");
//	return 0;

	QApplication app(argc, argv);

	//
	// setup opengl viewer
	//
	GLModelViewer glwidget;
	glwidget.resize(640, 480);
	glwidget.setPerspective(60.0f, 0.1f, 1024.0f);
	glwidget.move(320, 0);
	glwidget.setWindowTitle("Point Cloud");
	glwidget.setWeelSpeed(0.1f);
	glwidget.setDistance(-0.5f);
	glwidget.show();

	Eigen::Matrix4d to_origin = Eigen::Matrix4d::Identity();
	to_origin.col(3) << -(volume_size.x() / 2.0), -(volume_size.y() / 2.0), -(volume_size.z() / 2.0), 1.0;	// set translate

	std::vector<Eigen::Vector4f> vertices, colors;

	int i = 0;
	for (int z = 0; z <= volume_size.z(); z += voxel_size.z())
	{
		for (int y = 0; y <= volume_size.y(); y += voxel_size.y())
		{
			for (int x = 0; x <= volume_size.x(); x += voxel_size.x(), i++)
			{
				const float tsdf = grid.data.at(i).tsdf;

				if (tsdf > 0.1)
				{
					Eigen::Vector4d p = grid_affine.matrix() * to_origin * Eigen::Vector4d(x, y, z, 1);
					p /= p.w();
					vertices.push_back(p.cast<float>());

					colors.push_back(Eigen::Vector4f(0, 1, 0, 1));
				}
				else if (tsdf < -0.1)
				{
					Eigen::Vector4d p = grid_affine.matrix() * to_origin * Eigen::Vector4d(x, y, z, 1);
					p /= p.w();
					vertices.push_back(p.cast<float>());

					colors.push_back(Eigen::Vector4f(1, 0, 0, 1));
				}

				if (tsdf > -0.1 && tsdf < 0.1)
				{

				}
			}
		}
	}

	//
	// setup model
	//
	std::shared_ptr<GLModel> model(new GLModel);
	model->initGL();
	model->setVertices(&vertices[0][0], vertices.size(), 4);
	model->setColors(&colors[0][0], colors.size(), 4);
	glwidget.addModel(model);

	//
	// setup kinect shader program
	//
	std::shared_ptr<GLShaderProgram> kinectShaderProgram(new GLShaderProgram);
	if (kinectShaderProgram->build("color.vert", "color.frag"))
		model->setShaderProgram(kinectShaderProgram);

	return app.exec();
}

<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_VALIDATION_HH
#define DUNE_STUFF_VALIDATION_HH

#include <ostream>
#include <string>
#include <boost/format.hpp>

#include <dune/stuff/common/misc.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/type_utils.hh>

namespace Dune {
namespace Stuff {
namespace Common {

/** \brief Base class for all Validators
 *  the idea is from dune-fem, only our class is an actual interface
 **/
template <class T, class Derived>
class ValidatorInterface
{
public:
  bool operator() (const T& value) const {
    return asImp()( value );
  }

  std::string msg() const {
    return asImp().msg();
  }
  void print(std::ostream& out) const {
    out << asImp().msg();
  }
protected:
  inline const Derived& asImp () const {
    return static_cast< const Derived& >( *this );
  }

  inline Derived& asImp () {
    return static_cast< Derived& >( *this );
  }
};

//! a class usable as a default validator
template< class T >
class ValidateAny
  : public ValidatorInterface< T, ValidateAny< T > >
{
  typedef ValidateAny< T >                      ThisType;
  typedef ValidatorInterface< T, ThisType >     BaseType;

public:
  inline ValidateAny() {}
  inline ValidateAny(const ThisType&) {}

  inline bool operator()(const T&) const {
    return true;
  }

  std::string msg() const {
      return "ValidateAny: all values should be valid... \n\n";
  }
};

//! validates arg iff in given list
template< class T, class ListImp = std::vector< T > >
class ValidateInList
  : public ValidatorInterface< T, ValidateInList< T, ListImp > >
{
  typedef ValidateInList< T, ListImp >          ThisType;
  typedef ValidatorInterface< T, ThisType >     BaseType;
  typedef ListImp                               ListType;
  ListType valid_list_;

public:
  ValidateInList(const ListType& valid_list)
    : valid_list_(valid_list)
  {}

  inline bool operator()(const T& val) const {
    return std::find(valid_list_.begin(), valid_list_.end(), val) != valid_list_.end();
  }

  std::string msg() const {
    return "ValidateInList: checked Parameter was not in valid list\n\n";
  }
};

//! validate arg iff less than value, obviously
template < class T >
class ValidateLess : public ValidatorInterface< T, ValidateLess< T > >
{
public:
    ValidateLess(const T& baseval)
        : baseval_(baseval)
    {}
    inline bool operator()(const T& val) const {
      return baseval_ < val;
    }

    std::string msg() const {
        return (boost::format("given value was invalid: not less than %s") % toString(baseval_)).str();
    }
private:
    const T baseval_;
};

//! validate arg iff greater than value, obviously
template < class T >
class ValidateGreater : public ValidatorInterface< T, ValidateGreater< T > >
{
public:
    ValidateGreater(const T& baseval)
        : baseval_(baseval)
    {}
    inline bool operator()(const T& val) const {
      return baseval_ > val;
    }

    std::string msg() const {
        return (boost::format("given value was invalid: not greater than %s") % toString(baseval_)).str();
    }
private:
    const T baseval_;
};

//! validate iff not Validator(arg)
template < class T, class Validator >
class ValidateInverse : public ValidatorInterface< T, ValidateInverse< T, Validator > >
{
public:
    ValidateInverse(const Validator validator = Validator())
        : validator_(validator)
    {}
    ValidateInverse(const T arg)
        : validator_(Validator(arg))
    {}
    inline bool operator()(const T& val) const {
        return !validator_(val);
      }

    std::string msg() const {
        return "Inverse condition failed: " + validator_.msg();
    }
private:
    const Validator validator_;
};

#define INVERSE_VALIDATE(V_NEW_NAME,V_BASE_NAME) \
    template < class T> \
    struct V_NEW_NAME : public ValidateInverse< T, V_BASE_NAME<T> >{ \
        template <typename... Types> \
        V_NEW_NAME(Types... args) \
            : ValidateInverse< T,V_BASE_NAME<T> >(args...) \
        {} \
    }

INVERSE_VALIDATE(ValidateNone,ValidateAny);
INVERSE_VALIDATE(ValidateGreaterOrEqual,ValidateLess);
INVERSE_VALIDATE(ValidateNotLess,ValidateLess);

//! validate arg iff arg \in [min,max]
template < class T >
class ValidateInterval : public ValidatorInterface< T, ValidateInterval< T > >
{
public:
    ValidateInterval(const T& min, const T& max)
        : min_(min)
        , max_(max)
    {}

    inline bool operator()(const T& val) const {
        const bool lowerOk = ValidateGreaterOrEqual<T> (val)(min_);
        const bool upperOk = ValidateGreaterOrEqual<T> (max_)(val);
        return lowerOk && upperOk;
    }

    std::string msg() const {
        return "given value was invalid: value not in given interval";
    }
private:
    const T min_;
    const T max_;
};

//! example partial specialisation
template <typename T>
struct Typename<ValidateAny<T> > {
  static std::string value() {
    return "Dune::Stuff::Common::Parameter::ValidateAny<T>";
  }
};

} //end namesapce Common
} //end namesapce Stuff
} //end namesapce Dune

template < class T, class Validator >
std::ostream operator << ( std::ostream& out,
                           const Dune::Stuff::Common::ValidatorInterface< T, Validator >& validator )
{
    return out << validator.msg();
}

#endif // DUNE_STUFF_VALIDATION_HH
<commit_msg>[parameter.validation] fix typo<commit_after>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_VALIDATION_HH
#define DUNE_STUFF_VALIDATION_HH

#include <ostream>
#include <string>
#include <boost/format.hpp>

#include <dune/stuff/common/misc.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/type_utils.hh>

namespace Dune {
namespace Stuff {
namespace Common {

/** \brief Base class for all Validators
 *  the idea is from dune-fem, only our class is an actual interface
 **/
template <class T, class Derived>
class ValidatorInterface
{
public:
  bool operator() (const T& value) const {
    return asImp()( value );
  }

  std::string msg() const {
    return asImp().msg();
  }
  void print(std::ostream& out) const {
    out << asImp().msg();
  }
protected:
  inline const Derived& asImp () const {
    return static_cast< const Derived& >( *this );
  }

  inline Derived& asImp () {
    return static_cast< Derived& >( *this );
  }
};

//! a class usable as a default validator
template< class T >
class ValidateAny
  : public ValidatorInterface< T, ValidateAny< T > >
{
  typedef ValidateAny< T >                      ThisType;
  typedef ValidatorInterface< T, ThisType >     BaseType;

public:
  inline ValidateAny() {}
  inline ValidateAny(const ThisType&) {}

  inline bool operator()(const T&) const {
    return true;
  }

  std::string msg() const {
      return "ValidateAny: all values should be valid... \n\n";
  }
};

//! validates arg iff in given list
template< class T, class ListImp = std::vector< T > >
class ValidateInList
  : public ValidatorInterface< T, ValidateInList< T, ListImp > >
{
  typedef ValidateInList< T, ListImp >          ThisType;
  typedef ValidatorInterface< T, ThisType >     BaseType;
  typedef ListImp                               ListType;
  ListType valid_list_;

public:
  ValidateInList(const ListType& valid_list)
    : valid_list_(valid_list)
  {}

  inline bool operator()(const T& val) const {
    return std::find(valid_list_.begin(), valid_list_.end(), val) != valid_list_.end();
  }

  std::string msg() const {
    return "ValidateInList: checked Parameter was not in valid list\n\n";
  }
};

//! validate arg iff less than value, obviously
template < class T >
class ValidateLess : public ValidatorInterface< T, ValidateLess< T > >
{
public:
    ValidateLess(const T& baseval)
        : baseval_(baseval)
    {}
    inline bool operator()(const T& val) const {
      return baseval_ < val;
    }

    std::string msg() const {
        return (boost::format("given value was invalid: not less than %s") % toString(baseval_)).str();
    }
private:
    const T baseval_;
};

//! validate arg iff greater than value, obviously
template < class T >
class ValidateGreater : public ValidatorInterface< T, ValidateGreater< T > >
{
public:
    ValidateGreater(const T& baseval)
        : baseval_(baseval)
    {}
    inline bool operator()(const T& val) const {
      return baseval_ > val;
    }

    std::string msg() const {
        return (boost::format("given value was invalid: not greater than %s") % toString(baseval_)).str();
    }
private:
    const T baseval_;
};

//! validate iff not Validator(arg)
template < class T, class Validator >
class ValidateInverse : public ValidatorInterface< T, ValidateInverse< T, Validator > >
{
public:
    ValidateInverse(const Validator validator = Validator())
        : validator_(validator)
    {}
    ValidateInverse(const T arg)
        : validator_(Validator(arg))
    {}
    inline bool operator()(const T& val) const {
        return !validator_(val);
      }

    std::string msg() const {
        return "Inverse condition failed: " + validator_.msg();
    }
private:
    const Validator validator_;
};

#define INVERSE_VALIDATE(V_NEW_NAME,V_BASE_NAME) \
    template < class T> \
    struct V_NEW_NAME : public ValidateInverse< T, V_BASE_NAME<T> >{ \
        template <typename... Types> \
        V_NEW_NAME(Types... args) \
            : ValidateInverse< T,V_BASE_NAME<T> >(args...) \
        {} \
    }

INVERSE_VALIDATE(ValidateNone,ValidateAny);
INVERSE_VALIDATE(ValidateGreaterOrEqual,ValidateLess);
INVERSE_VALIDATE(ValidateNotLess,ValidateLess);

//! validate arg iff arg \in [min,max]
template < class T >
class ValidateInterval : public ValidatorInterface< T, ValidateInterval< T > >
{
public:
    ValidateInterval(const T& min, const T& max)
        : min_(min)
        , max_(max)
    {}

    inline bool operator()(const T& val) const {
        const bool lowerOk = ValidateGreaterOrEqual<T> (val)(min_);
        const bool upperOk = ValidateGreaterOrEqual<T> (max_)(val);
        return lowerOk && upperOk;
    }

    std::string msg() const {
        return "given value was invalid: value not in given interval";
    }
private:
    const T min_;
    const T max_;
};

//! example partial specialisation
template <typename T>
struct Typename<ValidateAny<T> > {
  static std::string value() {
    return "Dune::Stuff::Common::Parameter::ValidateAny<T>";
  }
};

} //end namespace Common
} //end namespace Stuff
} //end namespace Dune

template < class T, class Validator >
std::ostream operator << ( std::ostream& out,
                           const Dune::Stuff::Common::ValidatorInterface< T, Validator >& validator )
{
    return out << validator.msg();
}

#endif // DUNE_STUFF_VALIDATION_HH
<|endoftext|>