<commit_before>
#include "CubeScape.h"

#include <iostream>
#include <math.h>

#include <glbinding/gl/gl.h>

#include "glutils.h"
#include "RawFile.h"

using namespace gl;

CubeScape::CubeScape()
: a_vertex(-1)
, u_transform(-1)
, u_time(-1)
, u_numcubes(-1)
, m_vao(0)
, m_indices(0)
, m_vertices(0)
, m_program(0)
, m_a(0.f)
, m_numcubes(16)
{
    static const char * vertSource = R"(
        #version 150 core

        in vec3 a_vertex;
        out float v_h;

        uniform sampler2D terrain;
        uniform float time;

        uniform int numcubes;

        void main()
        {
            float oneovernumcubes = 1.f / float(numcubes);
            vec2 uv = vec2(mod(gl_InstanceID, numcubes), floor(gl_InstanceID * oneovernumcubes)) * 2.0 * oneovernumcubes;

            vec3 v = a_vertex * oneovernumcubes - (1.0 - oneovernumcubes);
            v.xz  += uv;

            v_h = texture2D(terrain, uv * 0.5 + vec2(sin(time * 0.04), time * 0.02)).r * 2.0 / 3.0;

            if(a_vertex.y > 0.0)
                v.y += v_h;

            gl_Position = vec4(v, 1.0);
        })";

    static const char * geomSource = R"(
        #version 150 core

        uniform mat4 modelViewProjection;
        uniform int numcubes;

        in  float v_h[3];
        out float g_h;

        out vec2 g_uv;
        out vec3 g_normal;

        layout (triangles) in;
        layout (triangle_strip, max_vertices = 4) out;

        void main()
        {
            vec4 u = gl_in[1].gl_Position - gl_in[0].gl_Position;
            vec4 v = gl_in[2].gl_Position - gl_in[0].gl_Position;

            float f = mix(1.0, v.y * float(numcubes) * 0.5, step(1.0 / float(numcubes), v.y));

            vec3 n = cross(normalize((modelViewProjection * u).xyz), normalize((modelViewProjection * v).xyz));

            gl_Position = modelViewProjection * gl_in[0].gl_Position;
            g_uv = vec2(0.0, 0.0);
            g_normal = n;
            g_h = v_h[0];
            EmitVertex();

            gl_Position = modelViewProjection * gl_in[1].gl_Position;
            g_uv = vec2(1.0, 0.0);
            EmitVertex();

            gl_Position = modelViewProjection * gl_in[2].gl_Position;
            g_uv = vec2(0.0, f);
            EmitVertex();

            gl_Position = modelViewProjection * vec4((gl_in[0].gl_Position + u + v).xyz, 1.0);
            g_uv = vec2(1.0, f);
            EmitVertex();
        })";

    static const char * fragSource = R"(
        #version 150 core

        in float g_h;

        in vec2 g_uv;
        in vec3 g_normal;

        out vec4 fragColor;

        uniform sampler2D patches;

        void main()
        {
            vec3 n = normalize(g_normal);
            vec3 l = normalize(vec3(0.0, -0.5, 1.0));

            float lambert = dot(n, l);

            float t = (2.0 / 3.0 - g_h) * 1.5 * 4.0 - 1.0;
            vec2 uv = g_uv * vec2(0.25, 1.0);

            vec4 c0 = texture2D(patches, uv + max(floor(t), 0.0) * vec2(0.25, 0.0));
            vec4 c1 = texture2D(patches, uv + min(floor(t) + 1.0, 3.0) * vec2(0.25, 0.0));

            fragColor = mix(c0, c1, smoothstep(0.25, 0.75, fract(t))) * lambert;
        })";

    // create program

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    GLuint gs = glCreateShader(GL_GEOMETRY_SHADER);
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(vs, 1, &vertSource, nullptr);
    glCompileShader(vs);
    compile_info(vs);

    glShaderSource(gs, 1, &geomSource, nullptr);
    glCompileShader(gs);
    compile_info(gs);

    glShaderSource(fs, 1, &fragSource, nullptr);
    glCompileShader(fs);
    compile_info(fs);

    m_program = glCreateProgram();

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

    glLinkProgram(m_program);

    // create textures

    glGenTextures(2, m_textures);

    glBindTexture(GL_TEXTURE_2D, m_textures[0]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_REPEAT));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_REPEAT));

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_LINEAR));

    {
        RawFile terrain("data/cubescape/terrain.64.64.r.ub.raw");
        if (!terrain.isValid())
            std::cout << "warning: loading texture from " << terrain.filePath() << " failed.";

        glTexImage2D(GL_TEXTURE_2D, 0, static_cast<int>(GL_LUMINANCE8), 64, 64, 0, GL_RED, GL_UNSIGNED_BYTE, terrain.data());
    }

    glBindTexture(GL_TEXTURE_2D, m_textures[1]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_REPEAT));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_REPEAT));

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_NEAREST));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_NEAREST));

    {
        RawFile patches("data/cubescape/patches.64.16.rgb.ub.raw");
        if (!patches.isValid())
            std::cout << "warning: loading texture from " << patches.filePath() << " failed.";

        glTexImage2D(GL_TEXTURE_2D, 0, static_cast<int>(GL_RGB8), 64, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, patches.data());
    }

    // create cube

    static const GLfloat vertices_data[24] =
    {
        -1.f, -1.f, -1.f, // 0
        -1.f, -1.f,  1.f, // 1
        -1.f,  1.f, -1.f, // 2
        -1.f,  1.f,  1.f, // 3
         1.f, -1.f, -1.f, // 4
         1.f, -1.f,  1.f, // 5
         1.f,  1.f, -1.f, // 6
         1.f,  1.f,  1.f  // 7
    };

    static const GLubyte indices_data[18] = {
        2, 3, 6, 0, 1, 2, 1, 5, 3, 5, 4, 7, 4, 0, 6, 5, 1, 4 };

    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    glGenBuffers(1, &m_vertices);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertices);
    glBufferData(GL_ARRAY_BUFFER, (8 * 3) * sizeof(float), vertices_data, GL_STATIC_DRAW);

    glGenBuffers(1, &m_indices);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (6 * 3) * sizeof(GLubyte), indices_data, GL_STATIC_DRAW);

    // setup uniforms

    a_vertex = glGetAttribLocation(m_program, "a_vertex");
    glEnableVertexAttribArray(static_cast<GLuint>(a_vertex));

    glVertexAttribPointer(static_cast<GLuint>(a_vertex), 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    u_transform = glGetUniformLocation(m_program, "modelViewProjection");
    u_time = glGetUniformLocation(m_program, "time");
    u_numcubes = glGetUniformLocation(m_program, "numcubes");

    m_time = clock::now();

    GLint terrain = glGetUniformLocation(m_program, "terrain");
    GLint patches = glGetUniformLocation(m_program, "patches");

    // since only single program and single data is used, bind only once

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    glClearColor(0.f, 0.f, 0.f, 1.0f);

    glUseProgram(m_program);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_textures[0]);
    glUniform1i(terrain, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_textures[1]);
    glUniform1i(patches, 1);

    // view

    m_view = mat4::lookAt(0.f, 0.8f,-2.0f, 0.f, -1.2f, 0.f, 0.f, 1.f, 0.f);
}

CubeScape::~CubeScape()
{
    glDeleteBuffers(1, &m_vertices);
    glDeleteBuffers(1, &m_indices);

    glDeleteProgram(m_program);
}

void CubeScape::setNumCubes(int numCubes)
{
    m_numcubes = std::min(4096, std::max(1, numCubes));
}
int CubeScape::numCubes() const
{
    return m_numcubes;
}

void CubeScape::resize(int width, int height)
{
    m_projection = mat4::perspective(40.f, static_cast<GLfloat>(width) / static_cast<GLfloat>(height), 1.f, 4.f);

    glViewport(0, 0, width, height);
}

void CubeScape::draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - m_time);
    float t = static_cast<float>(ms.count()) * 1e-3f;

    const mat4 transform = m_projection * m_view * mat4::rotate(t * 0.1f, 0.f, 1.f, 0.f);

    glUniformMatrix4fv(u_transform, 1, GL_FALSE, &transform[0]);
    glUniform1f(u_time, t);
    glUniform1i(u_numcubes, m_numcubes);

    glDrawElementsInstanced(GL_TRIANGLES, 18, GL_UNSIGNED_BYTE, 0, m_numcubes * m_numcubes);
}
<commit_msg>Remove shadowed function warning<commit_after>
#include "CubeScape.h"

#include <iostream>
#include <math.h>

#include <glbinding/gl/gl.h>

#include "glutils.h"
#include "RawFile.h"

using namespace gl;

CubeScape::CubeScape()
: a_vertex(-1)
, u_transform(-1)
, u_time(-1)
, u_numcubes(-1)
, m_vao(0)
, m_indices(0)
, m_vertices(0)
, m_program(0)
, m_a(0.f)
, m_numcubes(16)
{
    static const char * vertSource = R"(
        #version 150 core

        in vec3 a_vertex;
        out float v_h;

        uniform sampler2D terrain;
        uniform float time;

        uniform int numcubes;

        void main()
        {
            float oneovernumcubes = 1.f / float(numcubes);
            vec2 uv = vec2(mod(gl_InstanceID, numcubes), floor(gl_InstanceID * oneovernumcubes)) * 2.0 * oneovernumcubes;

            vec3 v = a_vertex * oneovernumcubes - (1.0 - oneovernumcubes);
            v.xz  += uv;

            v_h = texture2D(terrain, uv * 0.5 + vec2(sin(time * 0.04), time * 0.02)).r * 2.0 / 3.0;

            if(a_vertex.y > 0.0)
                v.y += v_h;

            gl_Position = vec4(v, 1.0);
        })";

    static const char * geomSource = R"(
        #version 150 core

        uniform mat4 modelViewProjection;
        uniform int numcubes;

        in  float v_h[3];
        out float g_h;

        out vec2 g_uv;
        out vec3 g_normal;

        layout (triangles) in;
        layout (triangle_strip, max_vertices = 4) out;

        void main()
        {
            vec4 u = gl_in[1].gl_Position - gl_in[0].gl_Position;
            vec4 v = gl_in[2].gl_Position - gl_in[0].gl_Position;

            float f = mix(1.0, v.y * float(numcubes) * 0.5, step(1.0 / float(numcubes), v.y));

            vec3 n = cross(normalize((modelViewProjection * u).xyz), normalize((modelViewProjection * v).xyz));

            gl_Position = modelViewProjection * gl_in[0].gl_Position;
            g_uv = vec2(0.0, 0.0);
            g_normal = n;
            g_h = v_h[0];
            EmitVertex();

            gl_Position = modelViewProjection * gl_in[1].gl_Position;
            g_uv = vec2(1.0, 0.0);
            EmitVertex();

            gl_Position = modelViewProjection * gl_in[2].gl_Position;
            g_uv = vec2(0.0, f);
            EmitVertex();

            gl_Position = modelViewProjection * vec4((gl_in[0].gl_Position + u + v).xyz, 1.0);
            g_uv = vec2(1.0, f);
            EmitVertex();
        })";

    static const char * fragSource = R"(
        #version 150 core

        in float g_h;

        in vec2 g_uv;
        in vec3 g_normal;

        out vec4 fragColor;

        uniform sampler2D patches;

        void main()
        {
            vec3 n = normalize(g_normal);
            vec3 l = normalize(vec3(0.0, -0.5, 1.0));

            float lambert = dot(n, l);

            float t = (2.0 / 3.0 - g_h) * 1.5 * 4.0 - 1.0;
            vec2 uv = g_uv * vec2(0.25, 1.0);

            vec4 c0 = texture2D(patches, uv + max(floor(t), 0.0) * vec2(0.25, 0.0));
            vec4 c1 = texture2D(patches, uv + min(floor(t) + 1.0, 3.0) * vec2(0.25, 0.0));

            fragColor = mix(c0, c1, smoothstep(0.25, 0.75, fract(t))) * lambert;
        })";

    // create program

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    GLuint gs = glCreateShader(GL_GEOMETRY_SHADER);
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(vs, 1, &vertSource, nullptr);
    glCompileShader(vs);
    compile_info(vs);

    glShaderSource(gs, 1, &geomSource, nullptr);
    glCompileShader(gs);
    compile_info(gs);

    glShaderSource(fs, 1, &fragSource, nullptr);
    glCompileShader(fs);
    compile_info(fs);

    m_program = glCreateProgram();

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

    glLinkProgram(m_program);

    // create textures

    glGenTextures(2, m_textures);

    glBindTexture(GL_TEXTURE_2D, m_textures[0]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_REPEAT));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_REPEAT));

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_LINEAR));

    {
        RawFile terrain("data/cubescape/terrain.64.64.r.ub.raw");
        if (!terrain.isValid())
            std::cout << "warning: loading texture from " << terrain.filePath() << " failed.";

        glTexImage2D(GL_TEXTURE_2D, 0, static_cast<int>(GL_LUMINANCE8), 64, 64, 0, GL_RED, GL_UNSIGNED_BYTE, terrain.data());
    }

    glBindTexture(GL_TEXTURE_2D, m_textures[1]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_REPEAT));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_REPEAT));

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_NEAREST));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_NEAREST));

    {
        RawFile patches("data/cubescape/patches.64.16.rgb.ub.raw");
        if (!patches.isValid())
            std::cout << "warning: loading texture from " << patches.filePath() << " failed.";

        glTexImage2D(GL_TEXTURE_2D, 0, static_cast<int>(GL_RGB8), 64, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, patches.data());
    }

    // create cube

    static const GLfloat vertices_data[24] =
    {
        -1.f, -1.f, -1.f, // 0
        -1.f, -1.f,  1.f, // 1
        -1.f,  1.f, -1.f, // 2
        -1.f,  1.f,  1.f, // 3
         1.f, -1.f, -1.f, // 4
         1.f, -1.f,  1.f, // 5
         1.f,  1.f, -1.f, // 6
         1.f,  1.f,  1.f  // 7
    };

    static const GLubyte indices_data[18] = {
        2, 3, 6, 0, 1, 2, 1, 5, 3, 5, 4, 7, 4, 0, 6, 5, 1, 4 };

    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    glGenBuffers(1, &m_vertices);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertices);
    glBufferData(GL_ARRAY_BUFFER, (8 * 3) * sizeof(float), vertices_data, GL_STATIC_DRAW);

    glGenBuffers(1, &m_indices);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (6 * 3) * sizeof(GLubyte), indices_data, GL_STATIC_DRAW);

    // setup uniforms

    a_vertex = glGetAttribLocation(m_program, "a_vertex");
    glEnableVertexAttribArray(static_cast<GLuint>(a_vertex));

    glVertexAttribPointer(static_cast<GLuint>(a_vertex), 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    u_transform = glGetUniformLocation(m_program, "modelViewProjection");
    u_time = glGetUniformLocation(m_program, "time");
    u_numcubes = glGetUniformLocation(m_program, "numcubes");

    m_time = clock::now();

    GLint terrain = glGetUniformLocation(m_program, "terrain");
    GLint patches = glGetUniformLocation(m_program, "patches");

    // since only single program and single data is used, bind only once

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    glClearColor(0.f, 0.f, 0.f, 1.0f);

    glUseProgram(m_program);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_textures[0]);
    glUniform1i(terrain, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_textures[1]);
    glUniform1i(patches, 1);

    // view

    m_view = mat4::lookAt(0.f, 0.8f,-2.0f, 0.f, -1.2f, 0.f, 0.f, 1.f, 0.f);
}

CubeScape::~CubeScape()
{
    glDeleteBuffers(1, &m_vertices);
    glDeleteBuffers(1, &m_indices);

    glDeleteProgram(m_program);
}

void CubeScape::setNumCubes(int _numCubes)
{
    m_numcubes = std::min(4096, std::max(1, _numCubes));
}
int CubeScape::numCubes() const
{
    return m_numcubes;
}

void CubeScape::resize(int width, int height)
{
    m_projection = mat4::perspective(40.f, static_cast<GLfloat>(width) / static_cast<GLfloat>(height), 1.f, 4.f);

    glViewport(0, 0, width, height);
}

void CubeScape::draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - m_time);
    float t = static_cast<float>(ms.count()) * 1e-3f;

    const mat4 transform = m_projection * m_view * mat4::rotate(t * 0.1f, 0.f, 1.f, 0.f);

    glUniformMatrix4fv(u_transform, 1, GL_FALSE, &transform[0]);
    glUniform1f(u_time, t);
    glUniform1i(u_numcubes, m_numcubes);

    glDrawElementsInstanced(GL_TRIANGLES, 18, GL_UNSIGNED_BYTE, 0, m_numcubes * m_numcubes);
}
<|endoftext|>


<commit_before>#ifndef PK_META_GREATESTCOMMONDIVISOR_HPP
#define PK_META_GREATESTCOMMONDIVISOR_HPP

namespace pk
{
namespace meta
{
namespace detail
{

template<bool BGreaterThanZero, int A, int B>
struct greatest_common_divisor
{
    static const int value = A;
};

template<int A, int B>
struct greatest_common_divisor<true, A, B>
{
private:
    static const int AA = B;
    static const int BB = A % B;

public:
    static const int value = greatest_common_divisor<(BB > 0), AA, BB>::value;
};

} // namespace detail

template<int A, int B>
struct greatest_common_divisor
{
    static const int value = detail::greatest_common_divisor<(B > 0), A, B>::value;
};

} // namespace meta
} // namespace pk

#endif // PK_META_GREATESTCOMMONDIVISOR_HPP
<commit_msg>Simplified gcd implementation<commit_after>#ifndef PK_META_GREATESTCOMMONDIVISOR_HPP
#define PK_META_GREATESTCOMMONDIVISOR_HPP

namespace pk
{
namespace meta
{

template<int A, int B>
struct greatest_common_divisor
{
    static const int value = greatest_common_divisor<B, A % B>::value;
};

template<int A>
struct greatest_common_divisor<A, 0>
{
    static const int value = A;
};

} // namespace meta
} // namespace pk

#endif // PK_META_GREATESTCOMMONDIVISOR_HPP
<|endoftext|>


<commit_before>#include "TransmitCom.h"

void flashSequence(char sequence, uint16_t ered, uint16_t  egreen, uint16_t eblue)
{

    uint16_t red, green, blue, c;

    bool buff[12];
    encodeASCII(sequence, buff[2],buff[4],buff[5],buff[6],buff[8],buff[9],buff[10],buff[11]);
    addParity(buff[2],buff[4],buff[5],buff[6],buff[8],buff[9],buff[10],buff[11], buff[0],buff[1],buff[3],buff[7]);

    Serial.print(sequence);
    Serial.print(": ");

    tcs.getRawData(&red, &green, &blue, &c);
    while(green < egreen*2)
    {
        tcs.getRawData(&red, &green, &blue, &c);
    }
    bool first = true;
    int j = 0;
    while(j<12)
    {
        if(!first)
        {
            tcs.getRawData(&red, &green, &blue, &c);
            while(blue > eblue*2)
            {
                tcs.getRawData(&red, &green, &blue, &c);
            }
            while(blue < eblue*2)
            {
                tcs.getRawData(&red, &green, &blue, &c);
            }
        }

        first = false;

        flashDotOrDash(2, buff[j]);
        j++;

        flashDotOrDash(3, buff[j]);
        j++;

        flashDotOrDash(4, buff[j]);
        j++;
        }
        delay(1000);
    }
    Serial.println();

}

void flashDotOrDash(int color, bool dotOrDash)
{
    Serial.print(dotOrDash);
    if(dotOrDash)
        digitalWrite(color, HIGH);
    else
        digitalWrite(color, LOW);
}

void synchronization(int initDelay)
{
    digitalWrite(r, HIGH);
    delay(initDelay);
    digitalWrite(r, LOW);

    digitalWrite(g, HIGH);
    delay(initDelay);
    digitalWrite(g, LOW);

    digitalWrite(b, HIGH);
    delay(initDelay);
    digitalWrite(b, LOW);

    digitalWrite(r, HIGH);
    digitalWrite(g, HIGH);
    delay(initDelay);
    digitalWrite(r, LOW);
    digitalWrite(g, LOW);

    digitalWrite(r, HIGH);
    digitalWrite(b, HIGH);
    delay(initDelay);
    digitalWrite(r, LOW);
    digitalWrite(b, LOW);

    digitalWrite(g, HIGH);
    digitalWrite(b, HIGH);
    delay(initDelay);
    digitalWrite(g, LOW);
    digitalWrite(b, LOW);

    digitalWrite(r, HIGH);
    digitalWrite(g, HIGH);
    digitalWrite(b, HIGH);
    delay(initDelay);
    digitalWrite(r, LOW);
    digitalWrite(g, LOW);
    digitalWrite(b, LOW);
    delay(initDelay);
}
<commit_msg>Delete TransmitCom.cpp<commit_after><|endoftext|>


<commit_before>/* Siconos-Kernel, Copyright INRIA 2005-2012.
* Siconos is a program dedicated to modeling, simulation and control
* of non smooth dynamical systems.
* Siconos is a free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Siconos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Siconos; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* Contact: Vincent ACARY, siconos-team@lists.gforge.inria.fr
*/

/*! \file SiconosVisitor.hpp
  \brief A general visitor interface for siconos objects.
*/

#ifndef SiconosVisitor_hpp
#define SiconosVisitor_hpp

/** A visitor pattern.

   \author SICONOS Development Team - copyright INRIA
   \version 3.0.0.
   \date (Creation) June 14, 2009

   User have to instantiate a derivation of SiconosVisitor class :

   struct myvisitor : public SiconosVisitor

   with some wanted visit() functions.

   Then the visitor can be used as :

   A_visitable_Siconos_Object->accept(Siconos::Visitor myvisitor)

   SiconosVisitor also define a type visitor object under the
   namespace Type:: and some functions to access type of visitables
   classes:

   Type::value(c) : the type of the visitable object c as an enum.

   Type::name(c)  : the name of the Type::value as a std::string

*/

#include "SiconosPointers.hpp"
#include "RuntimeException.hpp"

/* all Siconos classes that may be visited are defined there */
#include "SiconosVisitables.hpp"

/* convenient macros */
#define SICONOS_VISITOR_QUOTE(M) #M

#define SICONOS_VISITOR_FAIL(X)                                         \
  { RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(you must define a visit function for X in a derived class of SiconosVisitor)); }

/** hook to be inserted in a virtual class definiton */
#define VIRTUAL_ACCEPT_VISITORS(FROMCLASS)                              \
  template<typename Archive> friend class SiconosSerializer;            \
  virtual void acceptSP(SP::SiconosVisitor)                             \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(this class derived from FROMCLASS does not accept a visitor for shared pointers)); \
  };                                                                    \
  virtual void accept(SiconosVisitor&) const                            \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( "accept: no visitor defined");                     \
  };                                                                    \
  virtual void acceptSerializer(SiconosVisitor&)                        \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( "acceptSerializer: no serializer defined");                                           \
  };                                                                    \
  virtual inline Type::Siconos acceptType(FindType& ft) const           \
  { RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(this class derived from FROMCLASS does not accept a type visitor)); \
    return Type::void_type;                                             \
  }                                                                     \

/** hooks to be inserted in class definition */
#define ACCEPT_STD_VISITORS()                                           \
  template<typename Archive> friend class SiconosSerializer;            \
  virtual void accept(SiconosVisitor& tourist) const { tourist.visit(*this); } \
  virtual void acceptSerializer(SiconosVisitor& serializer) { serializer.visit(*this); } \
  virtual inline Type::Siconos acceptType(FindType& ft) const { return ft.visit(*this); } \

#define ACCEPT_NONVIRTUAL_VISITORS()                                           \
  template<typename Archive> friend class SiconosSerializer;            \
  void accept(SiconosVisitor& tourist) const { tourist.visit(*this); } \
  void acceptSerializer(SiconosVisitor& serializer) { serializer.visit(*this); } \
  inline Type::Siconos acceptType(FindType& ft) const { return ft.visit(*this); } \

#define ACCEPT_SP_VISITORS()                                            \
  virtual void acceptSP(SP::SiconosVisitor tourist) { tourist->visit(shared_from_this()); }

#define ACCEPT_VISITORS()                       \
  ACCEPT_SP_VISITORS()                          \
  ACCEPT_STD_VISITORS()                         \

/* objects that may be visited (1) */
#undef REGISTER
#undef REGISTER_STRUCT

#define REGISTER(X) class X;
#define REGISTER_STRUCT(X) struct X;

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)
#define REGISTER_BASE_EXTERN(X,Y) REGISTER(X)

SICONOS_VISITABLES()

/* associated types */
#undef REGISTER
#undef REGISTER_STRUCT
#define REGISTER(X) X,

#define REGISTER_STRUCT(X) X,

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)
#define REGISTER_BASE_EXTERN(X,Y) REGISTER(X)
namespace Type
{
enum Siconos
{
  SICONOS_VISITABLES()
  void_type
};
}

//namespace Siconos
//{

/* the type visitor */
#undef REGISTER
#define REGISTER(X)                                                 \
  virtual Type::Siconos visit(const X&) const { return Type::X; };  \

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y)                                         \
  virtual Type::Siconos visit(const X&) const { return Type::Y; }; \

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

struct FindType
{
  SICONOS_VISITABLES()
};

/* the base visitor */
#undef REGISTER
#define REGISTER(X)             \
  virtual void visit(std11::shared_ptr<X>) SICONOS_VISITOR_FAIL(SP :: X); \
  virtual void visit(X&) SICONOS_VISITOR_FAIL(X);                         \
  virtual void visit(const X&) SICONOS_VISITOR_FAIL(X);

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

struct SiconosVisitor
{
  SICONOS_VISITABLES()
  virtual ~SiconosVisitor() {};
};

/* some functions in Type namespace */
namespace Type
{
static FindType find;

template <typename C>
inline Siconos value(const C& c)
{
  return c.acceptType(find);
}

#undef REGISTER
#define REGISTER(X) case Type:: X : r.reset(new std::string(#X)); break;

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)
#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

inline std11::shared_ptr<std::string> str(const Siconos& X)
{
  std11::shared_ptr<std::string> r;

  switch (X)
  {
    SICONOS_VISITABLES()
  default:
    assert(0);
  }

  return(r);
}

template <class C>
std::string name(const C& c)
{
  return *(Type::str(Type::value(c)));
}

}

/* ask something to a class with a visitor */

/* example :
 *
 * struct ForMass : public Question<SP::SiconosMatrix>
 * {
 *    void visit(const LagrangianDS& ds)
 *    {
 *       Question::answer = ds.mass();
 *    }
 *
 * }
 * SP::DynamicalSystem ds
 * [...]
 *
 * SP::SiconosMatrix mass = ask<ForMass>(*ds);
 */

/** get some value from a visitable object with the help of a
    GeneralQuestion
    \param v a visitable object
 */
template <class GeneralQuestion, class Visitable>
typename GeneralQuestion::type ask(const Visitable& v)
{
  GeneralQuestion t;

  v.accept(t);

  return t.answer;

}

/** get some value from a visitable object with the help of a
    parameterized GeneralQuestion
    \param v a visitable object
    \param arg the GeneralQuestion argument
 */
template <class GeneralQuestion, class Visitable, class Argument>
typename GeneralQuestion::type ask(const Visitable& v, const Argument& arg)
{
  GeneralQuestion t(arg);

  v.accept(t);

  return t.answer;

}

/** apply a SiconosVisitor to a visitable object
 * \param v a visitable object
 */
template <class Visitor, class Visitable>
void apply(const Visitable& v)
{
  static Visitor t;

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg the SiconosVisitor argument
 */
template <class VisitorWithArgument, class Visitable, class Argument>
void apply(const Visitable& v, const Argument& arg)
{
  VisitorWithArgument t(arg);

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg1 the first SiconosVisitor argument
 * \param arg2 the second SiconosVisitor argument
 */
template <class VisitorWith2Arguments, class Visitable, class Argument1, class Argument2>
void apply(const Visitable& v, const Argument1& arg1, const Argument2& arg2)
{
  VisitorWith2Arguments t(arg1, arg2);

  v.accept(t);

}

/* use boost array for the initialization of non const reference */
//#include <boost/type_traits.hpp>
#if (__cplusplus >= 201103L) && !defined(USE_BOOST_FOR_CXX11)
#include <type_traits>
#include <array>
#else
#include <boost/type_traits/remove_reference.hpp>
#include <boost/array.hpp>
#endif

/** a generic return value visitor */
template <class AnswerType>
struct Question : public SiconosVisitor
{
  typedef AnswerType type;
  type answer;

  Question() : answer(std11::array<typename std11::remove_reference<AnswerType>::type, 1>()[0])
  {};
  Question(AnswerType ref) : answer(ref) {};

};

#define ANSWER(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = ds . CODE;                         \
  }

#define ANSWER_V(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE;                              \
  }

#define ANSWER_F(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE(ds);                          \
  }

TYPEDEF_SPTR(SiconosVisitor)

#undef REGISTER
#undef REGISTER_STRUCT
#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN

#endif /* SiconosVisitor_hpp */
<commit_msg>add Poly::Visitor to visit multiple types with same polyvisit function<commit_after>/* Siconos-Kernel, Copyright INRIA 2005-2012.
* Siconos is a program dedicated to modeling, simulation and control
* of non smooth dynamical systems.
* Siconos is a free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Siconos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Siconos; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* Contact: Vincent ACARY, siconos-team@lists.gforge.inria.fr
*/

/*! \file SiconosVisitor.hpp
  \brief A general visitor interface for siconos objects.
*/

#ifndef SiconosVisitor_hpp
#define SiconosVisitor_hpp

/** A visitor pattern.

   \author SICONOS Development Team - copyright INRIA
   \version 3.0.0.
   \date (Creation) June 14, 2009

   User has to instantiate a derivation of SiconosVisitor class :

   struct myvisitor : public SiconosVisitor
   {
     void visit(const LagrangianDS& ds)
     {
       ...
     }
   }

   with some wanted visit() functions.

   Then the visitor may be used as :

   A_visitable_Siconos_Object->accept(Siconos::Visitor myvisitor)

   SiconosVisitor also define a type visitor object under the
   namespace Type:: and some functions to access type of visitables
   classes:

   Type::value(c) : the type of the visitable object c as an enum.

   Type::name(c)  : the name of the Type::value as a std::string

*/

#include "SiconosPointers.hpp"
#include "RuntimeException.hpp"

/* all Siconos classes that may be visited are defined there */
#include "SiconosVisitables.hpp"

/* convenient macros */
#define SICONOS_VISITOR_QUOTE(M) #M

#define SICONOS_VISITOR_FAIL(X)                                         \
  { RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(you must define a visit function for X in a derived class of SiconosVisitor)); }

/** hook to be inserted in a virtual class definiton */
#define VIRTUAL_ACCEPT_VISITORS(FROMCLASS)                              \
  template<typename Archive> friend class SiconosSerializer;            \
  virtual void acceptSP(SP::SiconosVisitor)                             \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(this class derived from FROMCLASS does not accept a visitor for shared pointers)); \
  };                                                                    \
  virtual void accept(SiconosVisitor&) const                            \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( "accept: no visitor defined");                     \
  };                                                                    \
  virtual void acceptSerializer(SiconosVisitor&)                        \
  {                                                                     \
    RuntimeException::selfThrow                                         \
      ( "acceptSerializer: no serializer defined");                                           \
  };                                                                    \
  virtual inline Type::Siconos acceptType(FindType& ft) const           \
  { RuntimeException::selfThrow                                         \
      ( SICONOS_VISITOR_QUOTE(this class derived from FROMCLASS does not accept a type visitor)); \
    return Type::void_type;                                             \
  }                                                                     \

/** hooks to be inserted in class definition */
#define ACCEPT_STD_VISITORS()                                           \
  template<typename Archive> friend class SiconosSerializer;            \
  virtual void accept(SiconosVisitor& tourist) const { tourist.visit(*this); } \
  virtual void acceptSerializer(SiconosVisitor& serializer) { serializer.visit(*this); } \
  virtual inline Type::Siconos acceptType(FindType& ft) const { return ft.visit(*this); } \

#define ACCEPT_NONVIRTUAL_VISITORS()                                           \
  template<typename Archive> friend class SiconosSerializer;            \
  void accept(SiconosVisitor& tourist) const { tourist.visit(*this); } \
  void acceptSerializer(SiconosVisitor& serializer) { serializer.visit(*this); } \
  inline Type::Siconos acceptType(FindType& ft) const { return ft.visit(*this); } \

#define ACCEPT_SP_VISITORS()                                            \
  virtual void acceptSP(SP::SiconosVisitor tourist) { tourist->visit(shared_from_this()); }

#define ACCEPT_VISITORS()                       \
  ACCEPT_SP_VISITORS()                          \
  ACCEPT_STD_VISITORS()                         \

/* objects that may be visited (1) */
#undef REGISTER
#undef REGISTER_STRUCT

#define REGISTER(X) class X;
#define REGISTER_STRUCT(X) struct X;

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)
#define REGISTER_BASE_EXTERN(X,Y) REGISTER(X)

SICONOS_VISITABLES()

/* associated types */
#undef REGISTER
#undef REGISTER_STRUCT
#define REGISTER(X) X,

#define REGISTER_STRUCT(X) X,

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)
#define REGISTER_BASE_EXTERN(X,Y) REGISTER(X)
namespace Type
{
enum Siconos
{
  SICONOS_VISITABLES()
  void_type
};
}

//namespace Siconos
//{

/* the type visitor */
#undef REGISTER
#define REGISTER(X)                                                 \
  virtual Type::Siconos visit(const X&) const { return Type::X; };  \

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y)                                         \
  virtual Type::Siconos visit(const X&) const { return Type::Y; }; \

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

struct FindType
{
  SICONOS_VISITABLES()
};

/* the base visitor */
#undef REGISTER
#define REGISTER(X)             \
  virtual void visit(std11::shared_ptr<X>) SICONOS_VISITOR_FAIL(SP :: X); \
  virtual void visit(X&) SICONOS_VISITOR_FAIL(X);                         \
  virtual void visit(const X&) SICONOS_VISITOR_FAIL(X);

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)

#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

struct SiconosVisitor
{
  SICONOS_VISITABLES()
  virtual ~SiconosVisitor() {};
};

/* some functions in Type namespace */
namespace Type
{
static FindType find;

template <typename C>
inline Siconos value(const C& c)
{
  return c.acceptType(find);
}

#undef REGISTER
#define REGISTER(X) case Type:: X : r.reset(new std::string(#X)); break;

#undef REGISTER_STRUCT
#define REGISTER_STRUCT(X) REGISTER(X)
#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN
#define REGISTER_BASE(X,Y) REGISTER(X)

#define REGISTER_BASE_EXTERN(X,Y) REGISTER_BASE(X,Y)

inline std11::shared_ptr<std::string> str(const Siconos& X)
{
  std11::shared_ptr<std::string> r;

  switch (X)
  {
    SICONOS_VISITABLES()
  default:
    assert(0);
  }

  return(r);
}

template <class C>
std::string name(const C& c)
{
  return *(Type::str(Type::value(c)));
}

}

/* ask something to a class with a visitor */

/* example :
 *
 * struct ForMass : public Question<SP::SiconosMatrix>
 * {
 *    void visit(const LagrangianDS& ds)
 *    {
 *       Question::answer = ds.mass();
 *    }
 *
 * }
 * SP::DynamicalSystem ds
 * [...]
 *
 * SP::SiconosMatrix mass = ask<ForMass>(*ds);
 */

/** get some value from a visitable object with the help of a
    GeneralQuestion
    \param v a visitable object
 */
template <class GeneralQuestion, class Visitable>
typename GeneralQuestion::type ask(const Visitable& v)
{
  GeneralQuestion t;

  v.accept(t);

  return t.answer;

}

/** get some value from a visitable object with the help of a
    parameterized GeneralQuestion
    \param v a visitable object
    \param arg the GeneralQuestion argument
 */
template <class GeneralQuestion, class Visitable, class Argument>
typename GeneralQuestion::type ask(const Visitable& v, const Argument& arg)
{
  GeneralQuestion t(arg);

  v.accept(t);

  return t.answer;

}

/** apply a SiconosVisitor to a visitable object
 * \param v a visitable object
 */
template <class Visitor, class Visitable>
void apply(const Visitable& v)
{
  static Visitor t;

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg the SiconosVisitor argument
 */
template <class VisitorWithArgument, class Visitable, class Argument>
void apply(const Visitable& v, const Argument& arg)
{
  VisitorWithArgument t(arg);

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg1 the first SiconosVisitor argument
 * \param arg2 the second SiconosVisitor argument
 */
template <class VisitorWith2Arguments, class Visitable, class Argument1, class Argument2>
void apply(const Visitable& v, const Argument1& arg1, const Argument2& arg2)
{
  VisitorWith2Arguments t(arg1, arg2);

  v.accept(t);

}

/* use boost array for the initialization of non const reference */
//#include <boost/type_traits.hpp>
#if (__cplusplus >= 201103L) && !defined(USE_BOOST_FOR_CXX11)
#include <type_traits>
#include <array>
#else
#include <boost/type_traits/remove_reference.hpp>
#include <boost/array.hpp>
#endif

/** a generic return value visitor */
template <class AnswerType>
struct Question : public SiconosVisitor
{
  typedef AnswerType type;
  type answer;

  Question() : answer(std11::array<typename std11::remove_reference<AnswerType>::type, 1>()[0])
  {};
  Question(AnswerType ref) : answer(ref) {};

};

#define ANSWER(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = ds . CODE;                         \
  }

#define ANSWER_V(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE;                              \
  }

#define ANSWER_F(T,CODE) \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE(ds);                          \
  }

TYPEDEF_SPTR(SiconosVisitor)

#undef REGISTER
#undef REGISTER_STRUCT
#undef REGISTER_BASE
#undef REGISTER_BASE_EXTERN

namespace Poly {
template<typename T, typename Pred>
struct VisitMaker : public Pred
{
  using SiconosVisitor::visit;

  virtual void visit(const T& x)
  {
    Pred::polyvisit(x);
  }
};

struct empty {};

template<typename T1 = empty, typename T2 = empty,
         typename T3 = empty, typename T4 = empty,
         typename T5 = empty, typename T6 = empty,
         typename T7 = empty, typename T8 = empty,
         typename T9 = empty>
struct Visitor
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4,
                                                                   VisitMaker<T5,
                                                                              VisitMaker<T6,
                                                                                VisitMaker<T7,
                                                                                VisitMaker<T8,
                                                                                VisitMaker<T9, T> > > > > > > > >
  {};
};

template<typename T1>
struct Visitor<T1, empty, empty, empty, empty, empty, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1, T>{};
};

template<typename T1, typename T2>
struct Visitor<T1, T2, empty, empty, empty, empty, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1, VisitMaker<T2, T> >
  {};
};

template<typename T1, typename T2, typename T3>
struct Visitor<T1, T2, T3, empty, empty, empty, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3, T> > >
  {};
};

template<typename T1, typename T2, typename T3, typename T4>
struct Visitor<T1, T2, T3, T4, empty, empty, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4, T> > > >
  {};
};

template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Visitor<T1, T2, T3, T4, T5, empty, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4,
                                                                   VisitMaker<T5, T> > > > >
  {};
};

template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct Visitor<T1, T2, T3, T4, T5, T6, empty, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4,
                                                                   VisitMaker<T5, VisitMaker<T6, T>
                                                                              > > > > >
  {};
};

template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
struct Visitor<T1, T2, T3, T4, T5, T6, T7, empty, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4,
                                                                   VisitMaker<T5,
                                                                              VisitMaker<T6,
                                                                                VisitMaker<T7, T>
                                                                                > > > > > >
  {};
};

template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
struct Visitor<T1, T2, T3, T4, T5, T6, T7, T8, empty>
{
  template<typename T>
  struct Make : public VisitMaker<T1,
                                  VisitMaker<T2,
                                             VisitMaker<T3,
                                                        VisitMaker<T4,
                                                                   VisitMaker<T5,
                                                                              VisitMaker<T6,
                                                                                VisitMaker<T7,
                                                                                VisitMaker<T8, T>
                                                                                > > > > > > >
  {};
};

}

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


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2016 Daniel Baston
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: operation/distance/FacetSequence.java (f6187ee2 JTS-1.14)
 *
 **********************************************************************/

#include <geos/algorithm/Distance.h>
#include <geos/operation/distance/FacetSequence.h>

#include <memory>

using namespace geos::geom;
using namespace geos::operation::distance;
using namespace geos::algorithm;

FacetSequence::FacetSequence(const Geometry *p_geom, const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
    pts(p_pts),
    start(p_start),
    end(p_end),
    geom(p_geom)
{
    computeEnvelope();
}

FacetSequence::FacetSequence(const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
    pts(p_pts),
    start(p_start),
    end(p_end),
    geom(nullptr)
{
    computeEnvelope();
}

size_t
FacetSequence::size() const
{
    return end - start;
}

bool
FacetSequence::isPoint() const
{
    return end - start == 1;
}

double
FacetSequence::distance(const FacetSequence& facetSeq) const
{
    bool isPointThis = isPoint();
    bool isPointOther = facetSeq.isPoint();

    if(isPointThis && isPointOther) {
        const Coordinate& pt = pts->getAt(start);
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        return pt.distance(seqPt);
    }
    else if(isPointThis) {
        const Coordinate& pt = pts->getAt(start);
        return computeDistancePointLine(pt, facetSeq, nullptr);
    }
    else if(isPointOther) {
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        return computeDistancePointLine(seqPt, *this, nullptr);
    }
    else {
        return computeDistanceLineLine(facetSeq, nullptr);
    }
}

/*
* Rather than get bent out of shape about returning a pointer
* just return the whole mess, since it only ends up holding two
* locations.
*/
std::vector<GeometryLocation>
FacetSequence::nearestLocations(const FacetSequence& facetSeq)  const
{
    bool isPointThis = isPoint();
    bool isPointOther = facetSeq.isPoint();
    std::vector<GeometryLocation> locs;
    if (isPointThis && isPointOther) {
        const Coordinate& pt = pts->getAt(start);
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        GeometryLocation gl1(geom, start, pt);
        GeometryLocation gl2(facetSeq.geom, facetSeq.start, seqPt);
        locs.clear();
        locs.push_back(gl1);
        locs.push_back(gl2);
    }
    else if (isPointThis) {
        const Coordinate& pt = pts->getAt(start);
        computeDistancePointLine(pt, facetSeq, &locs);
    }
    else if (isPointOther) {
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        computeDistancePointLine(seqPt, *this, &locs);
        // unflip the locations
        GeometryLocation tmp = locs[0];
        locs[0] = locs[1];
        locs[1] = tmp;
    }
    else {
        computeDistanceLineLine(facetSeq, &locs);
    }
    return locs;
}

double
FacetSequence::computeDistancePointLine(const Coordinate& pt,
                                        const FacetSequence& facetSeq,
                                        std::vector<GeometryLocation> *locs) const
{
    double minDistance = std::numeric_limits<double>::infinity();

    for(size_t i = facetSeq.start; i < facetSeq.end - 1; i++) {
        const Coordinate& q0 = facetSeq.pts->getAt(i);
        const Coordinate& q1 = facetSeq.pts->getAt(i + 1);
        double dist = Distance::pointToSegment(pt, q0, q1);
        if(dist < minDistance) {
            minDistance = dist;
            if (locs != nullptr) {
                updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs);
            }
            if(minDistance <= 0.0) {
                return minDistance;
            }
        }
    }

    return minDistance;
}

void
FacetSequence::updateNearestLocationsPointLine(const Coordinate& pt,
        const FacetSequence& facetSeq, size_t i,
        const Coordinate& q0, const Coordinate &q1,
        std::vector<GeometryLocation> *locs) const
{
    geom::LineSegment seg(q0, q1);
    Coordinate segClosestPoint;
    seg.closestPoint(pt, segClosestPoint);
    locs->clear();
    locs->emplace_back(geom, start, pt);
    locs->emplace_back(facetSeq.geom, i, segClosestPoint);
    return;
}

double
FacetSequence::computeDistanceLineLine(const FacetSequence& facetSeq, std::vector<GeometryLocation> *locs) const
{
    double minDistance = std::numeric_limits<double>::infinity();
    double dist;

    for(size_t i = start; i < end - 1; i++) {
        const Coordinate& p0 = pts->getAt(i);
        const Coordinate& p1 = pts->getAt(i + 1);

        for(size_t j = facetSeq.start; j < facetSeq.end - 1; j++) {
            const Coordinate& q0 = facetSeq.pts->getAt(j);
            const Coordinate& q1 = facetSeq.pts->getAt(j + 1);

            dist = Distance::segmentToSegment(p0, p1, q0, q1);
            if(dist <= minDistance) {
                minDistance = dist;
                if(locs != nullptr) {
                    updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs);
                }
                if(minDistance <= 0.0) return minDistance;
            }
        }
    }

    return minDistance;
}

void
FacetSequence::updateNearestLocationsLineLine(size_t i, const Coordinate& p0, const Coordinate& p1,
        const FacetSequence& facetSeq,
        size_t j, const Coordinate& q0, const Coordinate &q1,
        std::vector<GeometryLocation> *locs) const
{
    LineSegment seg0(p0, p1);
    LineSegment seg1(q0, q1);

    auto closestPts = seg0.closestPoints(seg1);

    locs->clear();
    locs->emplace_back(geom, i, closestPts[0]);
    locs->emplace_back(facetSeq.geom, j, closestPts[1]);
}

void
FacetSequence::computeEnvelope()
{
    env = Envelope();
    for(size_t i = start; i < end; i++) {
        env.expandToInclude(pts->getX(i), pts->getY(i));
    }
}

const Envelope*
FacetSequence::getEnvelope() const
{
    return &env;
}

const Coordinate*
FacetSequence::getCoordinate(size_t index) const
{
    return &(pts->getAt(start + index));
}

<commit_msg>Optimize FacetSequence envelope calculation<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2016 Daniel Baston
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: operation/distance/FacetSequence.java (f6187ee2 JTS-1.14)
 *
 **********************************************************************/

#include <geos/algorithm/Distance.h>
#include <geos/operation/distance/FacetSequence.h>

#include <memory>

using namespace geos::geom;
using namespace geos::operation::distance;
using namespace geos::algorithm;

FacetSequence::FacetSequence(const Geometry *p_geom, const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
    pts(p_pts),
    start(p_start),
    end(p_end),
    geom(p_geom)
{
    computeEnvelope();
}

FacetSequence::FacetSequence(const CoordinateSequence* p_pts, size_t p_start, size_t p_end) :
    pts(p_pts),
    start(p_start),
    end(p_end),
    geom(nullptr)
{
    computeEnvelope();
}

size_t
FacetSequence::size() const
{
    return end - start;
}

bool
FacetSequence::isPoint() const
{
    return end - start == 1;
}

double
FacetSequence::distance(const FacetSequence& facetSeq) const
{
    bool isPointThis = isPoint();
    bool isPointOther = facetSeq.isPoint();

    if(isPointThis && isPointOther) {
        const Coordinate& pt = pts->getAt(start);
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        return pt.distance(seqPt);
    }
    else if(isPointThis) {
        const Coordinate& pt = pts->getAt(start);
        return computeDistancePointLine(pt, facetSeq, nullptr);
    }
    else if(isPointOther) {
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        return computeDistancePointLine(seqPt, *this, nullptr);
    }
    else {
        return computeDistanceLineLine(facetSeq, nullptr);
    }
}

/*
* Rather than get bent out of shape about returning a pointer
* just return the whole mess, since it only ends up holding two
* locations.
*/
std::vector<GeometryLocation>
FacetSequence::nearestLocations(const FacetSequence& facetSeq)  const
{
    bool isPointThis = isPoint();
    bool isPointOther = facetSeq.isPoint();
    std::vector<GeometryLocation> locs;
    if (isPointThis && isPointOther) {
        const Coordinate& pt = pts->getAt(start);
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        GeometryLocation gl1(geom, start, pt);
        GeometryLocation gl2(facetSeq.geom, facetSeq.start, seqPt);
        locs.clear();
        locs.push_back(gl1);
        locs.push_back(gl2);
    }
    else if (isPointThis) {
        const Coordinate& pt = pts->getAt(start);
        computeDistancePointLine(pt, facetSeq, &locs);
    }
    else if (isPointOther) {
        const Coordinate& seqPt = facetSeq.pts->getAt(facetSeq.start);
        computeDistancePointLine(seqPt, *this, &locs);
        // unflip the locations
        GeometryLocation tmp = locs[0];
        locs[0] = locs[1];
        locs[1] = tmp;
    }
    else {
        computeDistanceLineLine(facetSeq, &locs);
    }
    return locs;
}

double
FacetSequence::computeDistancePointLine(const Coordinate& pt,
                                        const FacetSequence& facetSeq,
                                        std::vector<GeometryLocation> *locs) const
{
    double minDistance = std::numeric_limits<double>::infinity();

    for(size_t i = facetSeq.start; i < facetSeq.end - 1; i++) {
        const Coordinate& q0 = facetSeq.pts->getAt(i);
        const Coordinate& q1 = facetSeq.pts->getAt(i + 1);
        double dist = Distance::pointToSegment(pt, q0, q1);
        if(dist < minDistance) {
            minDistance = dist;
            if (locs != nullptr) {
                updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs);
            }
            if(minDistance <= 0.0) {
                return minDistance;
            }
        }
    }

    return minDistance;
}

void
FacetSequence::updateNearestLocationsPointLine(const Coordinate& pt,
        const FacetSequence& facetSeq, size_t i,
        const Coordinate& q0, const Coordinate &q1,
        std::vector<GeometryLocation> *locs) const
{
    geom::LineSegment seg(q0, q1);
    Coordinate segClosestPoint;
    seg.closestPoint(pt, segClosestPoint);
    locs->clear();
    locs->emplace_back(geom, start, pt);
    locs->emplace_back(facetSeq.geom, i, segClosestPoint);
    return;
}

double
FacetSequence::computeDistanceLineLine(const FacetSequence& facetSeq, std::vector<GeometryLocation> *locs) const
{
    double minDistance = std::numeric_limits<double>::infinity();
    double dist;

    for(size_t i = start; i < end - 1; i++) {
        const Coordinate& p0 = pts->getAt(i);
        const Coordinate& p1 = pts->getAt(i + 1);

        for(size_t j = facetSeq.start; j < facetSeq.end - 1; j++) {
            const Coordinate& q0 = facetSeq.pts->getAt(j);
            const Coordinate& q1 = facetSeq.pts->getAt(j + 1);

            dist = Distance::segmentToSegment(p0, p1, q0, q1);
            if(dist <= minDistance) {
                minDistance = dist;
                if(locs != nullptr) {
                    updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs);
                }
                if(minDistance <= 0.0) return minDistance;
            }
        }
    }

    return minDistance;
}

void
FacetSequence::updateNearestLocationsLineLine(size_t i, const Coordinate& p0, const Coordinate& p1,
        const FacetSequence& facetSeq,
        size_t j, const Coordinate& q0, const Coordinate &q1,
        std::vector<GeometryLocation> *locs) const
{
    LineSegment seg0(p0, p1);
    LineSegment seg1(q0, q1);

    auto closestPts = seg0.closestPoints(seg1);

    locs->clear();
    locs->emplace_back(geom, i, closestPts[0]);
    locs->emplace_back(facetSeq.geom, j, closestPts[1]);
}

void
FacetSequence::computeEnvelope()
{
    env = Envelope();
    for(size_t i = start; i < end; i++) {
        env.expandToInclude(pts->getAt(i));
    }
}

const Envelope*
FacetSequence::getEnvelope() const
{
    return &env;
}

const Coordinate*
FacetSequence::getCoordinate(size_t index) const
{
    return &(pts->getAt(start + index));
}

<|endoftext|>


<commit_before>// ==========================================================================
// Line And Polygon Geometry
//
// Adapted from Sonny Chan's CPSC453 OpenGL Core Profile Boilerplate
// http://pages.cpsc.ucalgary.ca/~sonny.chan/cpsc453/resources/handouts/CPSC453-BoilerplateCode.zip
//
// Author:  Matthew Sembinelli, University of Calgary
// Date:    January 17, 2015
// ==========================================================================

#include <iostream>
#include <fstream>
#include <algorithm>

// specify that we want the OpenGL core profile before including GLFW headers
#define GLFW_INCLUDE_GLCOREARB
#define GL_GLEXT_PROTOTYPES
#include <GLFW/glfw3.h>

using namespace std;

// --------------------------------------------------------------------------
// OpenGL utility and support function prototypes

void QueryGLVersion();
bool CheckGLErrors();

string LoadSource(const string &filename);
GLuint CompileShader(GLenum shaderType, const string &source);
GLuint LinkProgram(GLuint vertexShader, GLuint fragmentShader);

// --------------------------------------------------------------------------
// Functions to set up OpenGL shader programs for rendering

struct MyShader
{
    // OpenGL names for vertex and fragment shaders, shader program
    GLuint  vertex;
    GLuint  fragment;
    GLuint  program;

    // initialize shader and program names to zero (OpenGL reserved value)
    MyShader() : vertex(0), fragment(0), program(0)
    {}
};

// load, compile, and link shaders, returning true if successful
bool InitializeShaders(MyShader *shader)
{
    // load shader source from files
    string vertexSource = LoadSource("vertex.glsl");
    string fragmentSource = LoadSource("fragment.glsl");
    if (vertexSource.empty() || fragmentSource.empty()) return false;

    // compile shader source into shader objects
    shader->vertex = CompileShader(GL_VERTEX_SHADER, vertexSource);
    shader->fragment = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);

    // link shader program
    shader->program = LinkProgram(shader->vertex, shader->fragment);

    // check for OpenGL errors and return false if error occurred
    return !CheckGLErrors();
}

// deallocate shader-related objects
void DestroyShaders(MyShader *shader)
{
    // unbind any shader programs and destroy shader objects
    glUseProgram(0);
    glDeleteProgram(shader->program);
    glDeleteShader(shader->vertex);
    glDeleteShader(shader->fragment);
}

// --------------------------------------------------------------------------
// Functions to set up OpenGL buffers for storing geometry data

struct MyGeometry
{
    // OpenGL names for array buffer objects, vertex array object
    GLuint  vertexBuffer;
    GLuint  colourBuffer;
    GLuint  vertexArray;
    GLsizei elementCount;

    // initialize object names to zero (OpenGL reserved value)
    MyGeometry() : vertexBuffer(0), colourBuffer(0), vertexArray(0), elementCount(0)
    {}
};

// create buffers and fill with geometry data, returning true if successful
bool InitializeGeometry(MyGeometry *geometry)
{
    //Draw square consisting of two triangles
    const GLfloat vertices[][2] = {
        { -0.5,  0.5 },
        { -0.5, -0.5 },
        {  0.5,  0.5 },
        {  0.5, -0.5 },
        { -0.5, -0.5 },
        {  0.5,  0.5 }
    };

    const GLfloat colours[][3] = {
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 }
    };
    geometry->elementCount = 6;

    // these vertex attribute indices correspond to those specified for the
    // input variables in the vertex shader
    const GLuint VERTEX_INDEX = 0;
    const GLuint COLOUR_INDEX = 1;

    // create an array buffer object for storing our vertices
    glGenBuffers(1, &geometry->vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, geometry->vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // create another one for storing our colours
    glGenBuffers(1, &geometry->colourBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, geometry->colourBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);

    // create a vertex array object encapsulating all our vertex attributes
    glGenVertexArrays(1, &geometry->vertexArray);
    glBindVertexArray(geometry->vertexArray);

    // associate the position array with the vertex array object
    glBindBuffer(GL_ARRAY_BUFFER, geometry->vertexBuffer);
    glVertexAttribPointer(VERTEX_INDEX, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(VERTEX_INDEX);

    // assocaite the colour array with the vertex array object
    glBindBuffer(GL_ARRAY_BUFFER, geometry->colourBuffer);
    glVertexAttribPointer(COLOUR_INDEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(COLOUR_INDEX);

    // unbind our buffers, resetting to default state
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // check for OpenGL errors and return false if error occurred
    return !CheckGLErrors();
}

// deallocate geometry-related objects
void DestroyGeometry(MyGeometry *geometry)
{
    // unbind and destroy our vertex array object and associated buffers
    glBindVertexArray(0);
    glDeleteVertexArrays(1, &geometry->vertexArray);
    glDeleteBuffers(1, &geometry->vertexBuffer);
    glDeleteBuffers(1, &geometry->colourBuffer);
}

// --------------------------------------------------------------------------
// Rendering function that draws our scene to the frame buffer

void RenderScene(MyGeometry *geometry, MyShader *shader)
{
    // clear screen to a dark grey colour
    glClearColor(0.2, 0.2, 0.2, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    // bind our shader program and the vertex array object containing our
    // scene geometry, then tell OpenGL to draw our geometry
    glUseProgram(shader->program);
    glBindVertexArray(geometry->vertexArray);
    glDrawArrays(GL_TRIANGLES, 0, geometry->elementCount);

    // reset state to default (no shader or geometry bound)
    glBindVertexArray(0);
    glUseProgram(0);

    // check for an report any OpenGL errors
    CheckGLErrors();
}

// --------------------------------------------------------------------------
// GLFW callback functions

// reports GLFW errors
void ErrorCallback(int error, const char* description)
{
    cout << "GLFW ERROR " << error << ":" << endl;
    cout << description << endl;
}

// handles keyboard input events
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
    {
    	switch(key)
    	{
    	case GLFW_KEY_F1:
    		break;
    	case GLFW_KEY_F2:
    		break;
    	case GLFW_KEY_F3:
    		break;
    	case GLFW_KEY_1:
    		break;
    	case GLFW_KEY_2:
    		break;
    	case GLFW_KEY_3:
    		break;
    	case GLFW_KEY_4:
    		break;
    	case GLFW_KEY_5:
    		break;
    	case GLFW_KEY_6:
    		break;
    	case GLFW_KEY_ESCAPE:
    		glfwSetWindowShouldClose(window, GL_TRUE);
    		break;
    	}
    }
}

// ==========================================================================
// PROGRAM ENTRY POINT

int main(int argc, char *argv[])
{
    // initialize the GLFW windowing system
    if (!glfwInit()) {
        cout << "ERROR: GLFW failed to initilize, TERMINATING" << endl;
        return -1;
    }
    glfwSetErrorCallback(ErrorCallback);

    // attempt to create a window with an OpenGL 4.1 core profile context
    GLFWwindow *window = 0;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    window = glfwCreateWindow(512, 512, "CPSC 453 Assignment 1 - Line And Polygon Geometry", 0, 0);
    if (!window) {
        cout << "Program failed to create GLFW window, TERMINATING" << endl;
        glfwTerminate();
        return -1;
    }

    // set keyboard callback function and make our context current (active)
    glfwSetKeyCallback(window, KeyCallback);
    glfwMakeContextCurrent(window);

    // query and print out information about our OpenGL environment
    QueryGLVersion();

    // call function to load and compile shader programs
    MyShader shader;
    if (!InitializeShaders(&shader)) {
        cout << "Program could not initialize shaders, TERMINATING" << endl;
        return -1;
    }

    // call function to create and fill buffers with geometry data
    MyGeometry geometry;
    if (!InitializeGeometry(&geometry))
        cout << "Program failed to intialize geometry!" << endl;

    // run an event-triggered main loop
    while (!glfwWindowShouldClose(window))
    {
        // call function to draw our scene
        RenderScene(&geometry, &shader);

        // scene is rendered to the back buffer, so swap to front for display
        glfwSwapBuffers(window);

        // sleep until next event before drawing again
        glfwWaitEvents();
    }

    // clean up allocated resources before exit
    DestroyGeometry(&geometry);
    DestroyShaders(&shader);
    glfwDestroyWindow(window);
    glfwTerminate();

    cout << "Goodbye!" << endl;
    return 0;
}

// ==========================================================================
// SUPPORT FUNCTION DEFINITIONS

// --------------------------------------------------------------------------
// OpenGL utility functions

void QueryGLVersion()
{
    // query opengl version and renderer information
    string version  = reinterpret_cast<const char *>(glGetString(GL_VERSION));
    string glslver  = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
    string renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));

    cout << "OpenGL [ " << version << " ] "
         << "with GLSL [ " << glslver << " ] "
         << "on renderer [ " << renderer << " ]" << endl;
}

bool CheckGLErrors()
{
    bool error = false;
    for (GLenum flag = glGetError(); flag != GL_NO_ERROR; flag = glGetError())
    {
        cout << "OpenGL ERROR:  ";
        switch (flag) {
        case GL_INVALID_ENUM:
            cout << "GL_INVALID_ENUM" << endl; break;
        case GL_INVALID_VALUE:
            cout << "GL_INVALID_VALUE" << endl; break;
        case GL_INVALID_OPERATION:
            cout << "GL_INVALID_OPERATION" << endl; break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            cout << "GL_INVALID_FRAMEBUFFER_OPERATION" << endl; break;
        case GL_OUT_OF_MEMORY:
            cout << "GL_OUT_OF_MEMORY" << endl; break;
        default:
            cout << "[unknown error code]" << endl;
        }
        error = true;
    }
    return error;
}

// --------------------------------------------------------------------------
// OpenGL shader support functions

// reads a text file with the given name into a string
string LoadSource(const string &filename)
{
    string source;

    ifstream input(filename.c_str());
    if (input) {
        copy(istreambuf_iterator<char>(input),
             istreambuf_iterator<char>(),
             back_inserter(source));
        input.close();
    }
    else {
        cout << "ERROR: Could not load shader source from file "
             << filename << endl;
    }

    return source;
}

// creates and returns a shader object compiled from the given source
GLuint CompileShader(GLenum shaderType, const string &source)
{
    // allocate shader object name
    GLuint shaderObject = glCreateShader(shaderType);

    // try compiling the source as a shader of the given type
    const GLchar *source_ptr = source.c_str();
    glShaderSource(shaderObject, 1, &source_ptr, 0);
    glCompileShader(shaderObject);

    // retrieve compile status
    GLint status;
    glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint length;
        glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, &length);
        string info(length, ' ');
        glGetShaderInfoLog(shaderObject, info.length(), &length, &info[0]);
        cout << "ERROR compiling shader:" << endl << endl;
        cout << source << endl;
        cout << info << endl;
    }

    return shaderObject;
}

// creates and returns a program object linked from vertex and fragment shaders
GLuint LinkProgram(GLuint vertexShader, GLuint fragmentShader)
{
    // allocate program object name
    GLuint programObject = glCreateProgram();

    // attach provided shader objects to this program
    if (vertexShader)   glAttachShader(programObject, vertexShader);
    if (fragmentShader) glAttachShader(programObject, fragmentShader);

    // try linking the program with given attachments
    glLinkProgram(programObject);

    // retrieve link status
    GLint status;
    glGetProgramiv(programObject, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint length;
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &length);
        string info(length, ' ');
        glGetProgramInfoLog(programObject, info.length(), &length, &info[0]);
        cout << "ERROR linking shader program:" << endl;
        cout << info << endl;
    }

    return programObject;
}

// ==========================================================================
<commit_msg>Added switch statement to switch between scenes<commit_after>// ==========================================================================
// Line And Polygon Geometry
//
// Adapted from Sonny Chan's CPSC453 OpenGL Core Profile Boilerplate
// http://pages.cpsc.ucalgary.ca/~sonny.chan/cpsc453/resources/handouts/CPSC453-BoilerplateCode.zip
//
// Author:  Matthew Sembinelli, University of Calgary
// Date:    January 17, 2015
// ==========================================================================

#include <iostream>
#include <fstream>
#include <algorithm>

// specify that we want the OpenGL core profile before including GLFW headers
#define GLFW_INCLUDE_GLCOREARB
#define GL_GLEXT_PROTOTYPES
#include <GLFW/glfw3.h>

using namespace std;

// --------------------------------------------------------------------------
// OpenGL utility and support function prototypes

void QueryGLVersion();
bool CheckGLErrors();

string LoadSource(const string &filename);
GLuint CompileShader(GLenum shaderType, const string &source);
GLuint LinkProgram(GLuint vertexShader, GLuint fragmentShader);

// --------------------------------------------------------------------------
// Functions to set up OpenGL shader programs for rendering

struct MyShader
{
    // OpenGL names for vertex and fragment shaders, shader program
    GLuint  vertex;
    GLuint  fragment;
    GLuint  program;

    // initialize shader and program names to zero (OpenGL reserved value)
    MyShader() : vertex(0), fragment(0), program(0)
    {}
};

// load, compile, and link shaders, returning true if successful
bool InitializeShaders(MyShader *shader)
{
    // load shader source from files
    string vertexSource = LoadSource("vertex.glsl");
    string fragmentSource = LoadSource("fragment.glsl");
    if (vertexSource.empty() || fragmentSource.empty()) return false;

    // compile shader source into shader objects
    shader->vertex = CompileShader(GL_VERTEX_SHADER, vertexSource);
    shader->fragment = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);

    // link shader program
    shader->program = LinkProgram(shader->vertex, shader->fragment);

    // check for OpenGL errors and return false if error occurred
    return !CheckGLErrors();
}

// deallocate shader-related objects
void DestroyShaders(MyShader *shader)
{
    // unbind any shader programs and destroy shader objects
    glUseProgram(0);
    glDeleteProgram(shader->program);
    glDeleteShader(shader->vertex);
    glDeleteShader(shader->fragment);
}

// --------------------------------------------------------------------------
// Functions to set up OpenGL buffers for storing geometry data

struct MyGeometry
{
    // OpenGL names for array buffer objects, vertex array object
    GLuint  vertexBuffer;
    GLuint  colourBuffer;
    GLuint  vertexArray;
    GLsizei elementCount;

    // initialize object names to zero (OpenGL reserved value)
    MyGeometry() : vertexBuffer(0), colourBuffer(0), vertexArray(0), elementCount(0)
    {}
};

bool InitializeSquaresAndDiamonds(MyGeometry *geometry,  int iter){ return true; }

bool InitializeParametricSpiral(MyGeometry *geometry,  int iter){ return true; }

bool InitializeSierpinskiTriangle(MyGeometry *geometry,  int iter){ return true; }

// create buffers and fill with geometry data, returning true if successful
bool InitializeGeometry(MyGeometry *geometry, int iter)
{
    //Draw square consisting of two triangles
    const GLfloat vertices[][2] = {
        {  0.0,  0.5 },
        {  0.5, 0.5 },
        {  0.0,  0.0 },
        {  0.5, -0.5 },
        { -0.5, -0.5 },
        {  0.5,  0.5 }
    };

    const GLfloat colours[][3] = {
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 }
    };
    geometry->elementCount = 6;

    // these vertex attribute indices correspond to those specified for the
    // input variables in the vertex shader
    const GLuint VERTEX_INDEX = 0;
    const GLuint COLOUR_INDEX = 1;

    // create an array buffer object for storing our vertices
    glGenBuffers(1, &geometry->vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, geometry->vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // create another one for storing our colours
    glGenBuffers(1, &geometry->colourBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, geometry->colourBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);

    // create a vertex array object encapsulating all our vertex attributes
    glGenVertexArrays(1, &geometry->vertexArray);
    glBindVertexArray(geometry->vertexArray);

    // associate the position array with the vertex array object
    glBindBuffer(GL_ARRAY_BUFFER, geometry->vertexBuffer);
    glVertexAttribPointer(VERTEX_INDEX, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(VERTEX_INDEX);

    // assocaite the colour array with the vertex array object
    glBindBuffer(GL_ARRAY_BUFFER, geometry->colourBuffer);
    glVertexAttribPointer(COLOUR_INDEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(COLOUR_INDEX);

    // unbind our buffers, resetting to default state
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // check for OpenGL errors and return false if error occurred
    return !CheckGLErrors();
}

// deallocate geometry-related objects
void DestroyGeometry(MyGeometry *geometry)
{
    // unbind and destroy our vertex array object and associated buffers
    glBindVertexArray(0);
    glDeleteVertexArrays(1, &geometry->vertexArray);
    glDeleteBuffers(1, &geometry->vertexBuffer);
    glDeleteBuffers(1, &geometry->colourBuffer);
}

// --------------------------------------------------------------------------
// Rendering function that draws our scene to the frame buffer

void RenderScene(MyGeometry *geometry, MyShader *shader)
{
    // clear screen to a dark grey colour
    glClearColor(0.2, 0.2, 0.2, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    // bind our shader program and the vertex array object containing our
    // scene geometry, then tell OpenGL to draw our geometry
    glUseProgram(shader->program);
    glBindVertexArray(geometry->vertexArray);
    glDrawArrays(GL_TRIANGLES, 0, geometry->elementCount);

    // reset state to default (no shader or geometry bound)
    glBindVertexArray(0);
    glUseProgram(0);

    // check for an report any OpenGL errors
    CheckGLErrors();
}

// --------------------------------------------------------------------------
// GLFW callback functions

// reports GLFW errors
void ErrorCallback(int error, const char* description)
{
    cout << "GLFW ERROR " << error << ":" << endl;
    cout << description << endl;
}

enum PolygonType
{
	SQUARES_DIAMONDS,
	PARAMETRIC_SPIRAL,
	SIERPINSKI_TRIANGLE
};

PolygonType poly_type = SQUARES_DIAMONDS;
int poly_iter = 1;

// handles keyboard input events
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
    {
    	switch(key)
    	{
    	case GLFW_KEY_F1:
    		poly_type = SQUARES_DIAMONDS;
    		poly_iter = 1;
    		break;
    	case GLFW_KEY_F2:
    		poly_type = PARAMETRIC_SPIRAL;
    		poly_iter = 1;
    		break;
    	case GLFW_KEY_F3:
    		poly_type = SIERPINSKI_TRIANGLE;
    		poly_iter = 1;
    		break;
    	case GLFW_KEY_1:
    		poly_iter = 1;
    		break;
    	case GLFW_KEY_2:
    		poly_iter = 2;
    		break;
    	case GLFW_KEY_3:
    		poly_iter = 3;
    		break;
    	case GLFW_KEY_4:
    		poly_iter = 4;
    		break;
    	case GLFW_KEY_5:
    		poly_iter = 5;
    		break;
    	case GLFW_KEY_6:
    		poly_iter = 6;
    		break;
    	case GLFW_KEY_ESCAPE:
    		glfwSetWindowShouldClose(window, GL_TRUE);
    		break;
    	}
    }
}

// ==========================================================================
// PROGRAM ENTRY POINT

int main(int argc, char *argv[])
{
    // initialize the GLFW windowing system
    if (!glfwInit()) {
        cout << "ERROR: GLFW failed to initilize, TERMINATING" << endl;
        return -1;
    }
    glfwSetErrorCallback(ErrorCallback);

    // attempt to create a window with an OpenGL 4.1 core profile context
    GLFWwindow *window = 0;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    window = glfwCreateWindow(512, 512, "CPSC 453 Assignment 1 - Line And Polygon Geometry", 0, 0);
    if (!window) {
        cout << "Program failed to create GLFW window, TERMINATING" << endl;
        glfwTerminate();
        return -1;
    }

    // set keyboard callback function and make our context current (active)
    glfwSetKeyCallback(window, KeyCallback);
    glfwMakeContextCurrent(window);

    // query and print out information about our OpenGL environment
    QueryGLVersion();

    // call function to load and compile shader programs
    MyShader shader;
    if (!InitializeShaders(&shader)) {
        cout << "Program could not initialize shaders, TERMINATING" << endl;
        return -1;
    }

    // call function to create and fill buffers with geometry data
    MyGeometry sd_geometry, ps_geometry, st_geometry;
    if (!InitializeGeometry(&sd_geometry, 1))
        cout << "Program failed to intialize geometry!" << endl;

    // run an event-triggered main loop
    while (!glfwWindowShouldClose(window))
    {
    	switch(poly_type)
    	{
    	case SQUARES_DIAMONDS:
    		InitializeSquaresAndDiamonds(&sd_geometry, poly_iter);
    		RenderScene(&sd_geometry, &shader);
    		break;
    	case PARAMETRIC_SPIRAL:
    		InitializeParametricSpiral(&ps_geometry, poly_iter);
    		RenderScene(&ps_geometry, &shader);
    		break;
    	case SIERPINSKI_TRIANGLE:
    		InitializeSierpinskiTriangle(&st_geometry, poly_iter);
    		RenderScene(&st_geometry, &shader);
    		break;
    	}

        // scene is rendered to the back buffer, so swap to front for display
        glfwSwapBuffers(window);

        // sleep until next event before drawing again
        glfwWaitEvents();
    }

    // clean up allocated resources before exit
    DestroyGeometry(&sd_geometry);
    DestroyGeometry(&ps_geometry);
    DestroyGeometry(&st_geometry);
    DestroyShaders(&shader);
    glfwDestroyWindow(window);
    glfwTerminate();

    cout << "Goodbye!" << endl;
    return 0;
}

// ==========================================================================
// SUPPORT FUNCTION DEFINITIONS

// --------------------------------------------------------------------------
// OpenGL utility functions

void QueryGLVersion()
{
    // query opengl version and renderer information
    string version  = reinterpret_cast<const char *>(glGetString(GL_VERSION));
    string glslver  = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
    string renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));

    cout << "OpenGL [ " << version << " ] "
         << "with GLSL [ " << glslver << " ] "
         << "on renderer [ " << renderer << " ]" << endl;
}

bool CheckGLErrors()
{
    bool error = false;
    for (GLenum flag = glGetError(); flag != GL_NO_ERROR; flag = glGetError())
    {
        cout << "OpenGL ERROR:  ";
        switch (flag) {
        case GL_INVALID_ENUM:
            cout << "GL_INVALID_ENUM" << endl; break;
        case GL_INVALID_VALUE:
            cout << "GL_INVALID_VALUE" << endl; break;
        case GL_INVALID_OPERATION:
            cout << "GL_INVALID_OPERATION" << endl; break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            cout << "GL_INVALID_FRAMEBUFFER_OPERATION" << endl; break;
        case GL_OUT_OF_MEMORY:
            cout << "GL_OUT_OF_MEMORY" << endl; break;
        default:
            cout << "[unknown error code]" << endl;
        }
        error = true;
    }
    return error;
}

// --------------------------------------------------------------------------
// OpenGL shader support functions

// reads a text file with the given name into a string
string LoadSource(const string &filename)
{
    string source;

    ifstream input(filename.c_str());
    if (input) {
        copy(istreambuf_iterator<char>(input),
             istreambuf_iterator<char>(),
             back_inserter(source));
        input.close();
    }
    else {
        cout << "ERROR: Could not load shader source from file "
             << filename << endl;
    }

    return source;
}

// creates and returns a shader object compiled from the given source
GLuint CompileShader(GLenum shaderType, const string &source)
{
    // allocate shader object name
    GLuint shaderObject = glCreateShader(shaderType);

    // try compiling the source as a shader of the given type
    const GLchar *source_ptr = source.c_str();
    glShaderSource(shaderObject, 1, &source_ptr, 0);
    glCompileShader(shaderObject);

    // retrieve compile status
    GLint status;
    glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint length;
        glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, &length);
        string info(length, ' ');
        glGetShaderInfoLog(shaderObject, info.length(), &length, &info[0]);
        cout << "ERROR compiling shader:" << endl << endl;
        cout << source << endl;
        cout << info << endl;
    }

    return shaderObject;
}

// creates and returns a program object linked from vertex and fragment shaders
GLuint LinkProgram(GLuint vertexShader, GLuint fragmentShader)
{
    // allocate program object name
    GLuint programObject = glCreateProgram();

    // attach provided shader objects to this program
    if (vertexShader)   glAttachShader(programObject, vertexShader);
    if (fragmentShader) glAttachShader(programObject, fragmentShader);

    // try linking the program with given attachments
    glLinkProgram(programObject);

    // retrieve link status
    GLint status;
    glGetProgramiv(programObject, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint length;
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &length);
        string info(length, ' ');
        glGetProgramInfoLog(programObject, info.length(), &length, &info[0]);
        cout << "ERROR linking shader program:" << endl;
        cout << info << endl;
    }

    return programObject;
}

// ==========================================================================
<|endoftext|>