<commit_before>#include <cassert>
#include <iostream>
#include <map>

#include <GLFW/glfw3.h>

#include <glbinding/Binding.h>
#include <glbinding/callbacks.h>
#include <glbinding/gl/gl.h>
#include <globjects/globjects.h>

#include <glm/gtc/matrix_transform.hpp>

#include <openll/GlyphRenderer.h>
#include <openll/FontLoader.h>
#include <openll/stages/GlyphPreparationStage.h>

#include <openll/FontFace.h>
#include <openll/GlyphSequence.h>
#include <openll/GlyphSequenceConfig.h>
#include <openll/Alignment.h>
#include <openll/LineAnchor.h>

#include <cpplocate/cpplocate.h>
#include <cpplocate/ModuleInfo.h>

using namespace gl;

//const auto lorem =
//R"(Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.)";

glm::uvec2 g_viewport{640, 480};
bool g_viewport_changed = true;

void onResize(GLFWwindow*, int width, int height)
{
    g_viewport = {width, height};
    g_viewport_changed = true;
}

void onKeyPress(GLFWwindow* window, int key, int, int action, int mods)
{
    if (key == 'Q' && action == GLFW_PRESS && mods == GLFW_MOD_CONTROL)
    {
        glfwSetWindowShouldClose(window, 1);
    }
}

void glInitialize()
{
    glbinding::Binding::initialize(false);
    glbinding::setCallbackMaskExcept(
        glbinding::CallbackMask::After | glbinding::CallbackMask::Parameters,
        {"glGetError"});
    glbinding::setAfterCallback([](const glbinding::FunctionCall& call) {
        const auto error = glGetError();
        if (error != GL_NO_ERROR)
        {
            std::cout << error << " in " << call.function->name()
                      << " with parameters:" << std::endl;
            for (const auto& parameter : call.parameters)
            {
                std::cout << "    " << parameter->asString() << std::endl;
            }
        }
    });
    globjects::init();
    std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
}

gloperate_text::GlyphVertexCloud preparePoint(const glm::vec2 origin, gloperate_text::FontFace * font, glm::uvec2 viewport) {
	const std::string pointText = R"(.)";

	std::vector<gloperate_text::GlyphSequence> sequences;

	gloperate_text::GlyphSequence sequence;
	std::u32string unicode_string(pointText.begin(), pointText.end());
	sequence.setString(unicode_string);

	sequence.setWordWrap(true);
	sequence.setLineWidth(500.f);
	sequence.setAlignment(gloperate_text::Alignment::Centered);
	sequence.setLineAnchor(gloperate_text::LineAnchor::Baseline);
	sequence.setFontFace(font);
	sequence.setFontSize(64.f);

	const glm::vec4 margins{ 0.f, 0.f, 0.f, 0.f };
	const float ppiScale = 1.f;

	// compute  transform matrix
	glm::mat4 transform;
	// translate to lower left in NDC
	transform = glm::translate(transform, glm::vec3(-1.f, -1.f, 0.f));
	// scale glyphs to NDC size
	transform = glm::scale(transform, 2.f / glm::vec3(viewport.x, viewport.y, 1.f));
	// scale glyphs to pixel size with respect to the displays ppi
	transform = glm::scale(transform, glm::vec3(ppiScale));
	// translate to origin in point space - scale origin within
	// margined extend (i.e., viewport with margined areas removed)
	const auto marginedExtent = glm::vec2(viewport.x, viewport.y) / ppiScale
		- glm::vec2(margins[3] + margins[1], margins[2] + margins[0]);
	transform = glm::translate(transform
		, glm::vec3((0.5f * origin + 0.5f) * marginedExtent, 0.f) + glm::vec3(margins[3], margins[2], 0.f));

	sequence.setAdditionalTransform(transform);

	sequences.push_back(sequence);

	return gloperate_text::prepareGlyphs(sequences, true);
}

gloperate_text::GlyphVertexCloud prepareGlyphSequences(const glm::vec2 origin, std::string string, gloperate_text::FontFace * font, const float fontSize, const gloperate_text::Alignment alignment, glm::uvec2 viewport)
{
	std::vector<gloperate_text::GlyphSequence> sequences;

	// font->setLinespace(1.25f);
	gloperate_text::GlyphSequence sequence;
	std::u32string unicode_string(string.begin(), string.end());
	sequence.setString(unicode_string);

    sequence.setWordWrap(true);
    sequence.setLineWidth(500.f);
	sequence.setAlignment(alignment);
	sequence.setLineAnchor(gloperate_text::LineAnchor::Baseline);
	sequence.setFontFace(font);
    sequence.setFontSize(fontSize);

    const glm::vec4 margins {0.f, 0.f, 0.f, 0.f};
    const float ppiScale = 1.f;

    // compute  transform matrix
    glm::mat4 transform;
    // translate to lower left in NDC
    transform = glm::translate(transform, glm::vec3(-1.f, -1.f, 0.f));
    // scale glyphs to NDC size
    transform = glm::scale(transform, 2.f / glm::vec3(viewport.x, viewport.y, 1.f));
    // scale glyphs to pixel size with respect to the displays ppi
    transform = glm::scale(transform, glm::vec3(ppiScale));
    // translate to origin in point space - scale origin within
    // margined extend (i.e., viewport with margined areas removed)
    const auto marginedExtent = glm::vec2(viewport.x, viewport.y) / ppiScale
       - glm::vec2(margins[3] + margins[1], margins[2] + margins[0]);
    transform = glm::translate(transform
       , glm::vec3((0.5f * origin + 0.5f) * marginedExtent, 0.f) + glm::vec3(margins[3], margins[2], 0.f));

    sequence.setAdditionalTransform(transform);
    sequences.push_back(sequence);
	//sequences.data()[0].setTransform(origin.data(), fontSize.data(), *font.data()
	//    , { viewport.data()->width(), viewport.data()->height() });

    return gloperate_text::prepareGlyphs(sequences, true);
}

void annotatePoint(std::vector<gloperate_text::GlyphVertexCloud> & vertexClouds, const glm::vec2 origin, const glm::vec2 offset, std::string string, gloperate_text::FontFace * font, const float fontSize, gloperate_text::Alignment alignment, glm::uvec2 viewport)
{
	vertexClouds.push_back(prepareGlyphSequences(origin+offset, string, font, fontSize, alignment, viewport));
	vertexClouds.push_back(preparePoint(origin, font, viewport));
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    auto window = glfwCreateWindow(g_viewport.x, g_viewport.y, "Text-Demo", 0, nullptr);

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    glInitialize();

    glfwSetWindowSizeCallback(window, onResize);
    glfwSetKeyCallback(window, onKeyPress);

    cpplocate::ModuleInfo moduleInfo = cpplocate::findModule("openll");
    std::string dataPath = moduleInfo.value("dataPath");

    gloperate_text::FontLoader loader;
    auto font = loader.load(dataPath + "/fonts/opensansr36.fnt");
    gloperate_text::GlyphRenderer renderer;

	auto config = gloperate_text::GlyphSequenceConfig(font);

	std::vector<gloperate_text::GlyphVertexCloud> vertexClouds;
    gloperate_text::GlyphVertexCloud cloud, cloud2;
	gloperate_text::GlyphVertexCloud point, point2;
    glClearColor(1.f, 1.f, 1.f, 1.f);

    while (!glfwWindowShouldClose(window))
    {
        if (g_viewport_changed)
        {
            std::cout << "updated viewport (" << g_viewport.x << ", " << g_viewport.y << ")" << std::endl;
            glViewport(0, 0, g_viewport.x, g_viewport.y);

			vertexClouds.clear();

			annotatePoint(vertexClouds, glm::vec2(-0.2f, 0), glm::vec2(0, 0.1f), "big, centered, for point below", font, 32.f, gloperate_text::Alignment::Centered, g_viewport);
			annotatePoint(vertexClouds, glm::vec2(0.2f, -0.2), glm::vec2(0, -0.1), "small, centered Annotation for point above", font, 16.f, gloperate_text::Alignment::Centered, g_viewport);

			annotatePoint(vertexClouds, glm::vec2(-0.2f, -0.6f), glm::vec2(0.1, 0), "smaller, left aligned Annotation for point on the left", font, 8.f, gloperate_text::Alignment::LeftAligned, g_viewport);
        }

        gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT);

        gl::glDepthMask(gl::GL_FALSE);
        gl::glEnable(gl::GL_CULL_FACE);
        gl::glEnable(gl::GL_BLEND);
        gl::glBlendFunc(gl::GL_SRC_ALPHA, gl::GL_ONE_MINUS_SRC_ALPHA);

		for (int i = 0; i < vertexClouds.size(); i++) {
			renderer.render(vertexClouds[i]);
		}

        gl::glDepthMask(gl::GL_TRUE);
        gl::glDisable(gl::GL_CULL_FACE);
        gl::glDisable(gl::GL_BLEND);

        g_viewport_changed = false;

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
}
<commit_msg>adapted example to show different configs. not all config options are used, yet.<commit_after>#include <cassert>
#include <iostream>
#include <map>

#include <GLFW/glfw3.h>

#include <glbinding/Binding.h>
#include <glbinding/callbacks.h>
#include <glbinding/gl/gl.h>
#include <globjects/globjects.h>

#include <glm/gtc/matrix_transform.hpp>

#include <openll/GlyphRenderer.h>
#include <openll/FontLoader.h>
#include <openll/stages/GlyphPreparationStage.h>

#include <openll/FontFace.h>
#include <openll/GlyphSequence.h>
#include <openll/GlyphSequenceConfig.h>
#include <openll/Alignment.h>
#include <openll/LineAnchor.h>

#include <cpplocate/cpplocate.h>
#include <cpplocate/ModuleInfo.h>

using namespace gl;

//const auto lorem =
//R"(Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.)";

glm::uvec2 g_viewport{640, 480};
bool g_viewport_changed = true;

void onResize(GLFWwindow*, int width, int height)
{
    g_viewport = {width, height};
    g_viewport_changed = true;
}

void onKeyPress(GLFWwindow* window, int key, int, int action, int mods)
{
    if (key == 'Q' && action == GLFW_PRESS && mods == GLFW_MOD_CONTROL)
    {
        glfwSetWindowShouldClose(window, 1);
    }
}

void glInitialize()
{
    glbinding::Binding::initialize(false);
    glbinding::setCallbackMaskExcept(
        glbinding::CallbackMask::After | glbinding::CallbackMask::Parameters,
        {"glGetError"});
    glbinding::setAfterCallback([](const glbinding::FunctionCall& call) {
        const auto error = glGetError();
        if (error != GL_NO_ERROR)
        {
            std::cout << error << " in " << call.function->name()
                      << " with parameters:" << std::endl;
            for (const auto& parameter : call.parameters)
            {
                std::cout << "    " << parameter->asString() << std::endl;
            }
        }
    });
    globjects::init();
    std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
}

gloperate_text::GlyphVertexCloud preparePoint(const glm::vec2 origin, gloperate_text::FontFace * font, glm::uvec2 viewport) {
	const std::string pointText = R"(.)";

	std::vector<gloperate_text::GlyphSequence> sequences;

	gloperate_text::GlyphSequence sequence;
	std::u32string unicode_string(pointText.begin(), pointText.end());
	sequence.setString(unicode_string);

	sequence.setWordWrap(true);
	sequence.setLineWidth(500.f);
	sequence.setAlignment(gloperate_text::Alignment::Centered);
	sequence.setLineAnchor(gloperate_text::LineAnchor::Baseline);
	sequence.setFontFace(font);
	sequence.setFontSize(64.f);

	const glm::vec4 margins{ 0.f, 0.f, 0.f, 0.f };
	const float ppiScale = 1.f;

	// compute  transform matrix
	glm::mat4 transform;
	// translate to lower left in NDC
	transform = glm::translate(transform, glm::vec3(-1.f, -1.f, 0.f));
	// scale glyphs to NDC size
	transform = glm::scale(transform, 2.f / glm::vec3(viewport.x, viewport.y, 1.f));
	// scale glyphs to pixel size with respect to the displays ppi
	transform = glm::scale(transform, glm::vec3(ppiScale));
	// translate to origin in point space - scale origin within
	// margined extend (i.e., viewport with margined areas removed)
	const auto marginedExtent = glm::vec2(viewport.x, viewport.y) / ppiScale
		- glm::vec2(margins[3] + margins[1], margins[2] + margins[0]);
	transform = glm::translate(transform
		, glm::vec3((0.5f * origin + 0.5f) * marginedExtent, 0.f) + glm::vec3(margins[3], margins[2], 0.f));

	sequence.setAdditionalTransform(transform);

	sequences.push_back(sequence);

	return gloperate_text::prepareGlyphs(sequences, true);
}

gloperate_text::GlyphVertexCloud prepareGlyphSequences(const glm::vec2 origin, std::string string, gloperate_text::FontFace * font, const float fontSize, const gloperate_text::Alignment alignment, glm::uvec2 viewport)
{
	std::vector<gloperate_text::GlyphSequence> sequences;

	// font->setLinespace(1.25f);
	gloperate_text::GlyphSequence sequence;
	std::u32string unicode_string(string.begin(), string.end());
	sequence.setString(unicode_string);

    sequence.setWordWrap(true);
    sequence.setLineWidth(500.f);
	sequence.setAlignment(alignment);
	sequence.setLineAnchor(gloperate_text::LineAnchor::Baseline);
	sequence.setFontFace(font);
    sequence.setFontSize(fontSize);

    const glm::vec4 margins {0.f, 0.f, 0.f, 0.f};
    const float ppiScale = 1.f;

    // compute  transform matrix
    glm::mat4 transform;
    // translate to lower left in NDC
    transform = glm::translate(transform, glm::vec3(-1.f, -1.f, 0.f));
    // scale glyphs to NDC size
    transform = glm::scale(transform, 2.f / glm::vec3(viewport.x, viewport.y, 1.f));
    // scale glyphs to pixel size with respect to the displays ppi
    transform = glm::scale(transform, glm::vec3(ppiScale));
    // translate to origin in point space - scale origin within
    // margined extend (i.e., viewport with margined areas removed)
    const auto marginedExtent = glm::vec2(viewport.x, viewport.y) / ppiScale
       - glm::vec2(margins[3] + margins[1], margins[2] + margins[0]);
    transform = glm::translate(transform
       , glm::vec3((0.5f * origin + 0.5f) * marginedExtent, 0.f) + glm::vec3(margins[3], margins[2], 0.f));

    sequence.setAdditionalTransform(transform);
    sequences.push_back(sequence);
	//sequences.data()[0].setTransform(origin.data(), fontSize.data(), *font.data()
	//    , { viewport.data()->width(), viewport.data()->height() });

    return gloperate_text::prepareGlyphs(sequences, true);
}

void annotatePoint(std::vector<gloperate_text::GlyphVertexCloud> & vertexClouds, const glm::vec2 origin, const glm::vec2 offset, std::string string, gloperate_text::FontFace * font, const float fontSize, gloperate_text::Alignment alignment, glm::uvec2 viewport)
{
	vertexClouds.push_back(prepareGlyphSequences(origin+offset, string, font, fontSize, alignment, viewport));
	vertexClouds.push_back(preparePoint(origin, font, viewport));
}

void annotatePointConfig(std::vector<gloperate_text::GlyphVertexCloud> & vertexClouds, const glm::vec2 origin, const glm::vec2 offset, std::string string, gloperate_text::GlyphSequenceConfig config, glm::uvec2 viewport)
{
	//TODO some config settings are still ignored! (e.g. color)
	vertexClouds.push_back(prepareGlyphSequences(origin + offset, string, config.fontFace(), config.fontSize(), config.alignment(), viewport));
	vertexClouds.push_back(preparePoint(origin, config.fontFace(), viewport));
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    auto window = glfwCreateWindow(g_viewport.x, g_viewport.y, "Text-Demo", 0, nullptr);

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    glInitialize();

    glfwSetWindowSizeCallback(window, onResize);
    glfwSetKeyCallback(window, onKeyPress);

    cpplocate::ModuleInfo moduleInfo = cpplocate::findModule("openll");
    std::string dataPath = moduleInfo.value("dataPath");

    gloperate_text::FontLoader loader;
    auto font = loader.load(dataPath + "/fonts/opensansr36.fnt");
    gloperate_text::GlyphRenderer renderer;

	auto config = gloperate_text::GlyphSequenceConfig(font);
	auto configBigRed = gloperate_text::GlyphSequenceConfig(font);
	configBigRed.setFontColor(glm::vec4(1.f, 0.f, 0.f, 1.f));
	configBigRed.setFontSize(32.f);

	std::vector<gloperate_text::GlyphVertexCloud> vertexClouds;
    gloperate_text::GlyphVertexCloud cloud, cloud2;
	gloperate_text::GlyphVertexCloud point, point2;
    glClearColor(1.f, 1.f, 1.f, 1.f);

    while (!glfwWindowShouldClose(window))
    {
        if (g_viewport_changed)
        {
            std::cout << "updated viewport (" << g_viewport.x << ", " << g_viewport.y << ")" << std::endl;
            glViewport(0, 0, g_viewport.x, g_viewport.y);

			vertexClouds.clear();

			//annotatePoint(vertexClouds, glm::vec2(-0.2f, 0), glm::vec2(0, 0.1f), "big, centered, for point below", font, 32.f, gloperate_text::Alignment::Centered, g_viewport);
			//annotatePoint(vertexClouds, glm::vec2(0.2f, -0.2f), glm::vec2(0, -0.1f), "small, centered Annotation for point above", font, 16.f, gloperate_text::Alignment::Centered, g_viewport);

			//annotatePoint(vertexClouds, glm::vec2(-0.2f, -0.6f), glm::vec2(0.1f, 0), "smaller, left aligned Annotation for point on the left", font, 8.f, gloperate_text::Alignment::LeftAligned, g_viewport);

			annotatePointConfig(vertexClouds, glm::vec2(-0.2f, 0), glm::vec2(0, 0.1), "annotated with default config", config, g_viewport);
			annotatePointConfig(vertexClouds, glm::vec2(0.2f, -0.2f), glm::vec2(0, -0.1f), "annotated with default config", config, g_viewport);
			annotatePointConfig(vertexClouds, glm::vec2(-0.2f, -0.6f), glm::vec2(0.1, 0), "annotated with default config", config, g_viewport);

			annotatePointConfig(vertexClouds, glm::vec2(-0.8f, 0.8f), glm::vec2(0.1, -0.1f), "annotated with big config", configBigRed, g_viewport);
        }

        gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT);

        gl::glDepthMask(gl::GL_FALSE);
        gl::glEnable(gl::GL_CULL_FACE);
        gl::glEnable(gl::GL_BLEND);
        gl::glBlendFunc(gl::GL_SRC_ALPHA, gl::GL_ONE_MINUS_SRC_ALPHA);

		for (int i = 0; i < vertexClouds.size(); i++) {
			renderer.render(vertexClouds[i]);
		}

        gl::glDepthMask(gl::GL_TRUE);
        gl::glDisable(gl::GL_CULL_FACE);
        gl::glDisable(gl::GL_BLEND);

        g_viewport_changed = false;

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
}
<|endoftext|>


<commit_before>#include "GQ_Characterize.hpp"

int main(){
	//Should print ELLIPSOID or 1
	GQ_Characterize* testEllip = new GQ_Characterize(1.0,1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testEllip;

/* TODO: Expand to all tests when the first one is debugged */
	//ONE_SHEET_HYPERBOLOID or 2
	GQ_Characterize* testOneSheet = new GQ_Characterize(1.0,1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testOneSheet;

	//TWO_SHEET_HYPERBOLOID or 3
	GQ_Characterize* testTwoSheet = new GQ_Characterize(-1.0,-1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testTwoSheet;

	//ELLIPTIC_CONE or 4
	GQ_Characterize* testEllCone = new GQ_Characterize(1.0,1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0);
	delete testEllCone;

	//ELLIPTIC_PARABOLOID or 5
	GQ_Characterize* testEllPara = new GQ_Characterize(1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0);
	delete testEllPara;

	//HYPERBOLIC_PARABOLOID or 6
	GQ_Characterize* testHypPara = new GQ_Characterize(1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0);
	delete testHypPara;

	//ELLIPTIC_CYL or 7
	GQ_Characterize* testEllCyl = new GQ_Characterize(1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testEllCyl;

	//HYPERBOLIC_CYL or 8
	GQ_Characterize* testHypCyl = new GQ_Characterize(1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0);
	delete testHypCyl;

	//PARABOLIC_CYL or 9
	GQ_Characterize* testParaCyl = new GQ_Characterize(1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0,0.0);
	delete testParaCyl;

	return 0;
}
<commit_msg>Added non-unit (rotated) tests, commented out unit tests (all pass)<commit_after>#include "GQ_Characterize.hpp"

int main(){

/*All unit tests currently successful when special case line is fully decommented
	//Should print ELLIPSOID
	GQ_Characterize* testEllip = new GQ_Characterize(1.0,1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testEllip;

	//ONE_SHEET_HYPERBOLOID
	GQ_Characterize* testOneSheet = new GQ_Characterize(1.0,1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testOneSheet;

	//TWO_SHEET_HYPERBOLOID
	GQ_Characterize* testTwoSheet = new GQ_Characterize(-1.0,-1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testTwoSheet;

	//ELLIPTIC_CONE
	GQ_Characterize* testEllCone = new GQ_Characterize(1.0,1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0);
	delete testEllCone;

	//ELLIPTIC_PARABOLOID
	GQ_Characterize* testEllPara = new GQ_Characterize(1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0);
	delete testEllPara;

	//HYPERBOLIC_PARABOLOID
	GQ_Characterize* testHypPara = new GQ_Characterize(1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0);
	delete testHypPara;

	//ELLIPTIC_CYL
	GQ_Characterize* testEllCyl = new GQ_Characterize(1.0,1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,-1.0);
	delete testEllCyl;

	//HYPERBOLIC_CYL
	GQ_Characterize* testHypCyl = new GQ_Characterize(1.0,-1.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0);
	delete testHypCyl;

	//PARABOLIC_CYL
	GQ_Characterize* testParaCyl = new GQ_Characterize(1.0, 0.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0,0.0);
	delete testParaCyl;

*/

//Begin Rotation tests
        //Should return ELLIPSOID
        GQ_Characterize* testRotEllip = new GQ_Characterize(103,125,66,-48,-12,-60,0,0,0,-294);
        delete testRotEllip;

        //ELLIPTIC_CONE
        GQ_Characterize* testRotCone = new GQ_Characterize(3,3,-1,2, 0,0,0,0,0,0);
        delete testRotCone;

        //ELLIPTIC_PARABOLOID
        GQ_Characterize* testRotEllParab = new GQ_Characterize(1,3,1,2,2,2,-2,4,2,12);
        delete testRotEllParab;

        //ELLIPTIC_CYLINDER
        GQ_Characterize* testRotEllCyl = new GQ_Characterize(5,2,5,-4,-2,-4,6,-12,18,3);
        delete testRotEllCyl;

	return 0;
}

<|endoftext|>


<commit_before>#include <osgTerrain/Terrain>

#include <iostream>
#include <string>

#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/io_utils>

#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>

bool Terrain_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool Terrain_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy Terrain_Proxy
(
    new osgTerrain::Terrain,
    "Terrain",
    "Object Terrain Group",
    Terrain_readLocalData,
    Terrain_writeLocalData
);

osg::TransferFunction* readTransferFunction(osgDB::Input& fr)
{
    osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;

    int entry = fr[0].getNoNestedBrackets();

    fr += 2;

    std::vector<osg::Vec4> colours;

    while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
    {
        bool itrAdvanced = false;
        if (fr.matchSequence("range %f %f"))
        {
            float minValue,maxValue;
            fr[1].getFloat(minValue);
            fr[2].getFloat(maxValue);

            tf->setInputRange(minValue,maxValue);

            fr += 3;
            itrAdvanced = true;
        }

        if (fr.matchSequence("color %f %f %f %f"))
        {
            float r,g,b,a;
            fr[1].getFloat(r);
            fr[2].getFloat(g);
            fr[3].getFloat(b);
            fr[4].getFloat(a);

            colours.push_back(osg::Vec4(r,g,b,a));

            fr += 5;
            itrAdvanced = true;
        }

        if (fr.matchSequence("color %f %f %f"))
        {
            float r,g,b;
            fr[1].getFloat(r);
            fr[2].getFloat(g);
            fr[3].getFloat(b);

            colours.push_back(osg::Vec4(r,g,b,1.0f));

            fr += 5;
            itrAdvanced = true;
        }

        if (!itrAdvanced)
        {
            if (fr[0].getStr()) osg::notify(osg::NOTICE)<<"TransferFunction - unreconised token : "<<fr[0].getStr() << std::endl;
            ++fr;
        }
    }

    // step over trailing }
    ++fr;

    if (!colours.empty())
    {
        tf->allocate(colours.size());
        for(unsigned int i=0; i<colours.size(); ++i)
        {
            tf->setValue(i, colours[i]);
        }
    }

    if (tf->getNumberCellsX()==0)
    {
        tf->allocate(6);
        tf->setValue(0, osg::Vec4(1.0,1.0,1.0,1.0));
        tf->setValue(1, osg::Vec4(1.0,0.0,1.0,1.0));
        tf->setValue(2, osg::Vec4(1.0,0.0,0.0,1.0));
        tf->setValue(3, osg::Vec4(1.0,1.0,0.0,1.0));
        tf->setValue(4, osg::Vec4(0.0,1.0,1.0,1.0));
        tf->setValue(5, osg::Vec4(0.0,1.0,0.0,1.0));
    }

    return tf.release();
}

bool Terrain_readLocalData(osg::Object& obj, osgDB::Input &fr)
{
    osgTerrain::Terrain& terrain = static_cast<osgTerrain::Terrain&>(obj);

    bool itrAdvanced = false;

    osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
    if (readObject.valid()) itrAdvanced = true;

    osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
    if (locator) terrain.setLocator(locator);

    if (fr.matchSequence("ElevationLayer {"))
    {
        int entry = fr[0].getNoNestedBrackets();
        fr += 2;

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            bool localAdvanced = false;

            osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
            osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
            if (readObject.valid()) localAdvanced = true;

            unsigned int minLevel=0;
            if (fr.read("MinLevel",minLevel))
            {
                itrAdvanced = true;
            }

            unsigned int maxLevel = MAXIMUM_NUMBER_OF_LEVELS;
            if (fr.read("MaxLevel",maxLevel))
            {
                itrAdvanced = true;
            }

            if (fr.matchSequence("ProxyLayer %s") || fr.matchSequence("ProxyLayer %w") )
            {
                osgTerrain::ProxyLayer* proxyLayer = new osgTerrain::ProxyLayer;
                proxyLayer->setFileName(fr[1].getStr());

                if (locator) proxyLayer->setLocator(locator);
                if (minLevel!=0) proxyLayer->setMinLevel(minLevel);
                if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) proxyLayer->setMaxLevel(maxLevel);

                terrain.setElevationLayer(proxyLayer);

                fr += 2;

                localAdvanced = true;
            }
            else
            {
                osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Layer>());
                osgTerrain::Layer* readLayer = dynamic_cast<osgTerrain::Layer*>(readObject.get());
                if (readLayer)
                {
                    if (locator) readLayer->setLocator(locator);
                    if (minLevel!=0) readLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) readLayer->setMaxLevel(maxLevel);

                    terrain.setElevationLayer(readLayer);
                }

                if (readObject.valid()) localAdvanced = true;
            }

            if (!localAdvanced) ++fr;
        }

        itrAdvanced = true;
    }

    bool firstMatched = false;
    if ((firstMatched = fr.matchSequence("ColorLayer %i {")) || fr.matchSequence("ColorLayer {") )
    {
        unsigned int layerNum = 0;
        if (firstMatched)
        {
            fr[1].getUInt(layerNum);
            ++fr;
        }

        int entry = fr[0].getNoNestedBrackets();
        fr += 2;

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            bool localAdvanced = false;

            osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
            osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
            if (readObject.valid()) localAdvanced = true;

            unsigned int minLevel=0;
            if (fr.read("MinLevel",minLevel))
            {
                itrAdvanced = true;
            }

            unsigned int maxLevel = MAXIMUM_NUMBER_OF_LEVELS;
            if (fr.read("MaxLevel",maxLevel))
            {
                itrAdvanced = true;
            }

            if (fr.matchSequence("ProxyFile %s") || fr.matchSequence("ProxyFile %w") )
            {
                osg::ref_ptr<osg::Object> image = osgDB::readObjectFile(std::string(fr[1].getStr())+".gdal");
                osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<osgTerrain::ProxyLayer*>(image.get());
                if (proxyLayer)
                {
                    if (locator) proxyLayer->setLocator(locator);
                    if (minLevel!=0) proxyLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) proxyLayer->setMaxLevel(maxLevel);

                    terrain.setColorLayer(layerNum, proxyLayer);
                }

                fr += 2;

                localAdvanced = true;
            }
            else
            {
                osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Layer>());
                osgTerrain::Layer* readLayer = dynamic_cast<osgTerrain::Layer*>(readObject.get());
                if (readLayer)
                {
                    if (locator) readLayer->setLocator(locator);
                    if (minLevel!=0) readLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) readLayer->setMaxLevel(maxLevel);

                    terrain.setColorLayer(layerNum, readLayer);
                }

                if (readObject.valid()) localAdvanced = true;
            }

            if (!localAdvanced) ++fr;
        }

        itrAdvanced = true;
    }

    if ((firstMatched = fr.matchSequence("ColorTransferFunction %i {")) || fr.matchSequence("ColorTransferFunction {") )
    {
        unsigned int layerNum = 0;
        if (firstMatched)
        {
             fr[1].getUInt(layerNum);
            ++fr;
        }

        osg::TransferFunction* tf = readTransferFunction(fr);
        if (tf) terrain.setColorTransferFunction(layerNum, tf);

        itrAdvanced = true;
    }

    if (fr[0].matchWord("ColorFilter"))
    {
        unsigned int layerNum = 0;
        if (fr.matchSequence("ColorFilter %i"))
        {
            fr[1].getUInt(layerNum);
            fr += 2;
        }
        else
        {
            ++fr;
        }

        if (fr[0].matchWord("NEAREST")) terrain.setColorFilter(layerNum, osgTerrain::Terrain::NEAREST);
        else if (fr[0].matchWord("LINEAR")) terrain.setColorFilter(layerNum, osgTerrain::Terrain::LINEAR);

        ++fr;
        itrAdvanced = true;
    }

    readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::TerrainTechnique>());
    if (readObject.valid())
    {
        terrain.setTerrainTechnique(dynamic_cast<osgTerrain::TerrainTechnique*>(readObject.get()));
        itrAdvanced = true;
    }

    return itrAdvanced;
}

bool Terrain_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
{
    const osgTerrain::Terrain& terrain = static_cast<const osgTerrain::Terrain&>(obj);

    int prec = fw.precision();
    fw.precision(15);

    if (terrain.getLocator())
    {
        fw.writeObject(*terrain.getLocator());
    }

    if (terrain.getElevationLayer())
    {
        fw.indent()<<"ElevationLayer {"<<std::endl;

        fw.moveIn();

        const osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<const osgTerrain::ProxyLayer*>(terrain.getElevationLayer());
        if (proxyLayer)
        {
            if (!proxyLayer->getFileName().empty())
            {
                const osgTerrain::Locator* locator = proxyLayer->getLocator();
                if (locator && !locator->getDefinedInFile())
                {
                    fw.writeObject(*locator);
                }

                if (proxyLayer->getMinLevel()!=0)
                {
                    fw.indent()<<"MinLevel "<<proxyLayer->getMinLevel()<<std::endl;
                }

                if (proxyLayer->getMaxLevel()!=MAXIMUM_NUMBER_OF_LEVELS)
                {
                    fw.indent()<<"MaxLevel "<<proxyLayer->getMaxLevel()<<std::endl;
                }

                fw.indent()<<"ProxyLayer "<<proxyLayer->getFileName()<<std::endl;
            }
        }
        else if (terrain.getElevationLayer())
        {
            fw.writeObject(*terrain.getElevationLayer());
        }

        fw.moveOut();

        fw.indent()<<"}"<<std::endl;
    }

    for(unsigned int i=0; i<terrain.getNumColorLayers(); ++i)
    {
        const osgTerrain::Layer* layer = terrain.getColorLayer(i);
        if (layer)
        {
            if (i>0)
            {
                fw.indent()<<"ColorLayer "<<i<<" {"<<std::endl;
            }
            else
            {
                fw.indent()<<"ColorLayer {"<<std::endl;
            }

            fw.moveIn();

            const osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<const osgTerrain::ProxyLayer*>(layer);
            if (proxyLayer)
            {
                const osgTerrain::Locator* locator = proxyLayer->getLocator();
                if (locator && !locator->getDefinedInFile())
                {
                    fw.writeObject(*locator);
                }

                if (proxyLayer->getMinLevel()!=0)
                {
                    fw.indent()<<"MinLevel "<<proxyLayer->getMinLevel()<<std::endl;
                }

                if (proxyLayer->getMaxLevel()!=MAXIMUM_NUMBER_OF_LEVELS)
                {
                    fw.indent()<<"MaxLevel "<<proxyLayer->getMaxLevel()<<std::endl;
                }

                if (!proxyLayer->getFileName().empty()) fw.indent()<<"ProxyLayer "<<proxyLayer->getFileName()<<std::endl;
            }
            else if (layer)
            {
                fw.writeObject(*terrain.getColorLayer(i));
            }

            fw.moveOut();

            fw.indent()<<"}"<<std::endl;
        }
    }

    if (terrain.getTerrainTechnique())
    {
        fw.writeObject(*terrain.getTerrainTechnique());
    }

    fw.precision(prec);

    return true;
}
<commit_msg>Added Node to Terrain serialization<commit_after>#include <osgTerrain/Terrain>

#include <iostream>
#include <string>

#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/io_utils>

#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>

bool Terrain_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool Terrain_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy Terrain_Proxy
(
    new osgTerrain::Terrain,
    "Terrain",
    "Object Node Terrain Group",
    Terrain_readLocalData,
    Terrain_writeLocalData
);

osg::TransferFunction* readTransferFunction(osgDB::Input& fr)
{
    osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;

    int entry = fr[0].getNoNestedBrackets();

    fr += 2;

    std::vector<osg::Vec4> colours;

    while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
    {
        bool itrAdvanced = false;
        if (fr.matchSequence("range %f %f"))
        {
            float minValue,maxValue;
            fr[1].getFloat(minValue);
            fr[2].getFloat(maxValue);

            tf->setInputRange(minValue,maxValue);

            fr += 3;
            itrAdvanced = true;
        }

        if (fr.matchSequence("color %f %f %f %f"))
        {
            float r,g,b,a;
            fr[1].getFloat(r);
            fr[2].getFloat(g);
            fr[3].getFloat(b);
            fr[4].getFloat(a);

            colours.push_back(osg::Vec4(r,g,b,a));

            fr += 5;
            itrAdvanced = true;
        }

        if (fr.matchSequence("color %f %f %f"))
        {
            float r,g,b;
            fr[1].getFloat(r);
            fr[2].getFloat(g);
            fr[3].getFloat(b);

            colours.push_back(osg::Vec4(r,g,b,1.0f));

            fr += 5;
            itrAdvanced = true;
        }

        if (!itrAdvanced)
        {
            if (fr[0].getStr()) osg::notify(osg::NOTICE)<<"TransferFunction - unreconised token : "<<fr[0].getStr() << std::endl;
            ++fr;
        }
    }

    // step over trailing }
    ++fr;

    if (!colours.empty())
    {
        tf->allocate(colours.size());
        for(unsigned int i=0; i<colours.size(); ++i)
        {
            tf->setValue(i, colours[i]);
        }
    }

    if (tf->getNumberCellsX()==0)
    {
        tf->allocate(6);
        tf->setValue(0, osg::Vec4(1.0,1.0,1.0,1.0));
        tf->setValue(1, osg::Vec4(1.0,0.0,1.0,1.0));
        tf->setValue(2, osg::Vec4(1.0,0.0,0.0,1.0));
        tf->setValue(3, osg::Vec4(1.0,1.0,0.0,1.0));
        tf->setValue(4, osg::Vec4(0.0,1.0,1.0,1.0));
        tf->setValue(5, osg::Vec4(0.0,1.0,0.0,1.0));
    }

    return tf.release();
}

bool Terrain_readLocalData(osg::Object& obj, osgDB::Input &fr)
{
    osgTerrain::Terrain& terrain = static_cast<osgTerrain::Terrain&>(obj);

    bool itrAdvanced = false;

    osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
    if (readObject.valid()) itrAdvanced = true;

    osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
    if (locator) terrain.setLocator(locator);

    if (fr.matchSequence("ElevationLayer {"))
    {
        int entry = fr[0].getNoNestedBrackets();
        fr += 2;

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            bool localAdvanced = false;

            osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
            osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
            if (readObject.valid()) localAdvanced = true;

            unsigned int minLevel=0;
            if (fr.read("MinLevel",minLevel))
            {
                itrAdvanced = true;
            }

            unsigned int maxLevel = MAXIMUM_NUMBER_OF_LEVELS;
            if (fr.read("MaxLevel",maxLevel))
            {
                itrAdvanced = true;
            }

            if (fr.matchSequence("ProxyLayer %s") || fr.matchSequence("ProxyLayer %w") )
            {
                osgTerrain::ProxyLayer* proxyLayer = new osgTerrain::ProxyLayer;
                proxyLayer->setFileName(fr[1].getStr());

                if (locator) proxyLayer->setLocator(locator);
                if (minLevel!=0) proxyLayer->setMinLevel(minLevel);
                if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) proxyLayer->setMaxLevel(maxLevel);

                terrain.setElevationLayer(proxyLayer);

                fr += 2;

                localAdvanced = true;
            }
            else
            {
                osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Layer>());
                osgTerrain::Layer* readLayer = dynamic_cast<osgTerrain::Layer*>(readObject.get());
                if (readLayer)
                {
                    if (locator) readLayer->setLocator(locator);
                    if (minLevel!=0) readLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) readLayer->setMaxLevel(maxLevel);

                    terrain.setElevationLayer(readLayer);
                }

                if (readObject.valid()) localAdvanced = true;
            }

            if (!localAdvanced) ++fr;
        }

        itrAdvanced = true;
    }

    bool firstMatched = false;
    if ((firstMatched = fr.matchSequence("ColorLayer %i {")) || fr.matchSequence("ColorLayer {") )
    {
        unsigned int layerNum = 0;
        if (firstMatched)
        {
            fr[1].getUInt(layerNum);
            ++fr;
        }

        int entry = fr[0].getNoNestedBrackets();
        fr += 2;

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            bool localAdvanced = false;

            osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Locator>());
            osgTerrain::Locator* locator = dynamic_cast<osgTerrain::Locator*>(readObject.get());
            if (readObject.valid()) localAdvanced = true;

            unsigned int minLevel=0;
            if (fr.read("MinLevel",minLevel))
            {
                itrAdvanced = true;
            }

            unsigned int maxLevel = MAXIMUM_NUMBER_OF_LEVELS;
            if (fr.read("MaxLevel",maxLevel))
            {
                itrAdvanced = true;
            }

            if (fr.matchSequence("ProxyFile %s") || fr.matchSequence("ProxyFile %w") )
            {
                osg::ref_ptr<osg::Object> image = osgDB::readObjectFile(std::string(fr[1].getStr())+".gdal");
                osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<osgTerrain::ProxyLayer*>(image.get());
                if (proxyLayer)
                {
                    if (locator) proxyLayer->setLocator(locator);
                    if (minLevel!=0) proxyLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) proxyLayer->setMaxLevel(maxLevel);

                    terrain.setColorLayer(layerNum, proxyLayer);
                }

                fr += 2;

                localAdvanced = true;
            }
            else
            {
                osg::ref_ptr<osg::Object> readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::Layer>());
                osgTerrain::Layer* readLayer = dynamic_cast<osgTerrain::Layer*>(readObject.get());
                if (readLayer)
                {
                    if (locator) readLayer->setLocator(locator);
                    if (minLevel!=0) readLayer->setMinLevel(minLevel);
                    if (maxLevel!=MAXIMUM_NUMBER_OF_LEVELS) readLayer->setMaxLevel(maxLevel);

                    terrain.setColorLayer(layerNum, readLayer);
                }

                if (readObject.valid()) localAdvanced = true;
            }

            if (!localAdvanced) ++fr;
        }

        itrAdvanced = true;
    }

    if ((firstMatched = fr.matchSequence("ColorTransferFunction %i {")) || fr.matchSequence("ColorTransferFunction {") )
    {
        unsigned int layerNum = 0;
        if (firstMatched)
        {
             fr[1].getUInt(layerNum);
            ++fr;
        }

        osg::TransferFunction* tf = readTransferFunction(fr);
        if (tf) terrain.setColorTransferFunction(layerNum, tf);

        itrAdvanced = true;
    }

    if (fr[0].matchWord("ColorFilter"))
    {
        unsigned int layerNum = 0;
        if (fr.matchSequence("ColorFilter %i"))
        {
            fr[1].getUInt(layerNum);
            fr += 2;
        }
        else
        {
            ++fr;
        }

        if (fr[0].matchWord("NEAREST")) terrain.setColorFilter(layerNum, osgTerrain::Terrain::NEAREST);
        else if (fr[0].matchWord("LINEAR")) terrain.setColorFilter(layerNum, osgTerrain::Terrain::LINEAR);

        ++fr;
        itrAdvanced = true;
    }

    readObject = fr.readObjectOfType(osgDB::type_wrapper<osgTerrain::TerrainTechnique>());
    if (readObject.valid())
    {
        terrain.setTerrainTechnique(dynamic_cast<osgTerrain::TerrainTechnique*>(readObject.get()));
        itrAdvanced = true;
    }

    return itrAdvanced;
}

bool Terrain_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
{
    const osgTerrain::Terrain& terrain = static_cast<const osgTerrain::Terrain&>(obj);

    int prec = fw.precision();
    fw.precision(15);

    if (terrain.getLocator())
    {
        fw.writeObject(*terrain.getLocator());
    }

    if (terrain.getElevationLayer())
    {
        fw.indent()<<"ElevationLayer {"<<std::endl;

        fw.moveIn();

        const osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<const osgTerrain::ProxyLayer*>(terrain.getElevationLayer());
        if (proxyLayer)
        {
            if (!proxyLayer->getFileName().empty())
            {
                const osgTerrain::Locator* locator = proxyLayer->getLocator();
                if (locator && !locator->getDefinedInFile())
                {
                    fw.writeObject(*locator);
                }

                if (proxyLayer->getMinLevel()!=0)
                {
                    fw.indent()<<"MinLevel "<<proxyLayer->getMinLevel()<<std::endl;
                }

                if (proxyLayer->getMaxLevel()!=MAXIMUM_NUMBER_OF_LEVELS)
                {
                    fw.indent()<<"MaxLevel "<<proxyLayer->getMaxLevel()<<std::endl;
                }

                fw.indent()<<"ProxyLayer "<<proxyLayer->getFileName()<<std::endl;
            }
        }
        else if (terrain.getElevationLayer())
        {
            fw.writeObject(*terrain.getElevationLayer());
        }

        fw.moveOut();

        fw.indent()<<"}"<<std::endl;
    }

    for(unsigned int i=0; i<terrain.getNumColorLayers(); ++i)
    {
        const osgTerrain::Layer* layer = terrain.getColorLayer(i);
        if (layer)
        {
            if (i>0)
            {
                fw.indent()<<"ColorLayer "<<i<<" {"<<std::endl;
            }
            else
            {
                fw.indent()<<"ColorLayer {"<<std::endl;
            }

            fw.moveIn();

            const osgTerrain::ProxyLayer* proxyLayer = dynamic_cast<const osgTerrain::ProxyLayer*>(layer);
            if (proxyLayer)
            {
                const osgTerrain::Locator* locator = proxyLayer->getLocator();
                if (locator && !locator->getDefinedInFile())
                {
                    fw.writeObject(*locator);
                }

                if (proxyLayer->getMinLevel()!=0)
                {
                    fw.indent()<<"MinLevel "<<proxyLayer->getMinLevel()<<std::endl;
                }

                if (proxyLayer->getMaxLevel()!=MAXIMUM_NUMBER_OF_LEVELS)
                {
                    fw.indent()<<"MaxLevel "<<proxyLayer->getMaxLevel()<<std::endl;
                }

                if (!proxyLayer->getFileName().empty()) fw.indent()<<"ProxyLayer "<<proxyLayer->getFileName()<<std::endl;
            }
            else if (layer)
            {
                fw.writeObject(*terrain.getColorLayer(i));
            }

            fw.moveOut();

            fw.indent()<<"}"<<std::endl;
        }
    }

    if (terrain.getTerrainTechnique())
    {
        fw.writeObject(*terrain.getTerrainTechnique());
    }

    fw.precision(prec);

    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */
#include <cassert>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <algorithm>
#include "hal.h"
#include "halMafWriteGenomes.h"

using namespace std;
using namespace hal;

MafWriteGenomes::MafWriteGenomes() : MafScanner()
{

}

MafWriteGenomes::~MafWriteGenomes()
{

}

void MafWriteGenomes::convert(const string& mafPath,
                              const string& refGenomeName,
                              const set<string>& targets,
                              const DimMap& dimMap,
                              AlignmentPtr alignment)
{
  _refName = refGenomeName;
  _dimMap = &dimMap;
  _alignment = alignment;
  _topSegment = TopSegmentIteratorPtr();
  _bottomSegment = BottomSegmentIteratorPtr();
  _refBottom = BottomSegmentIteratorPtr();
  _childIdxMap.clear();
  createGenomes();
  MafScanner::scan(mafPath, targets);
}

MafWriteGenomes::MapRange MafWriteGenomes::getRefSequences() const
{
  DimMap::const_iterator i = _dimMap->lower_bound(_refName);
  for (; i != _dimMap->end(); ++i)
  {
    if (genomeName(i->first) == _refName)
    {
      break;
    }
  }

  if (i == _dimMap->end())
  {
    stringstream ss;
    ss << "Reference genome " << _refName << " was not found in the MAF file.  "
       "Ie, no sequence in name in the form " << _refName << ".something was "
       "found.";
    throw hal_exception(ss.str());
  }

  DimMap::const_iterator j = i;
  for (; j != _dimMap->end(); ++j)
  {
    if (genomeName(j->first) != _refName)
    {
      break;
    }
  }

  return MapRange(i, j);
}

MafWriteGenomes::MapRange MafWriteGenomes::getNextSequences(
  DimMap::const_iterator jprev) const
{
  DimMap::const_iterator j = jprev;
  if (j == _dimMap->end())
  {
    return MapRange(j, j);
  }
  string name = genomeName(j->first);
  for (; j != _dimMap->end(); ++j)
  {
    if (genomeName(j->first) != name)
    {
      break;
    }
  }
  return MapRange(jprev, j);
}

void MafWriteGenomes::createGenomes()
{
  // need to create the tree before we do anything
  _refGenome = _alignment->openGenome(_refName);
  bool newRef = _refGenome == NULL;
  if (newRef)
  {
    if (_alignment->getNumGenomes() != 0)
    {
      throw hal_exception("Cannot add new reference to non-empty alignment");
    }
    _refGenome = _alignment->addRootGenome(_refName);
  }
  assert(_refGenome != NULL);

  // genomes comprise of ranges of sequences in the map.  do a quick
  // scan to add the children of _refGenome.
  MapRange refRange = getRefSequences();
  MapRange curRange = getNextSequences(_dimMap->begin());
  while (curRange.first != _dimMap->end())
  {
    if (curRange != refRange)
    {
      // note, we do not add a branch length.  will need to add option
      // to maf2hal where a tree can be given as well just for branch lengths
      _alignment->addLeafGenome(genomeName(curRange.first->first), _refName, 1);
    }
    curRange = getNextSequences(curRange.second);
  }

  // do the ref genome dimenions
  vector<Sequence::Info> genomeDimensions;
  vector<Sequence::UpdateInfo> updateDimensions;
  for (DimMap::const_iterator i = refRange.first; i != refRange.second; ++i)
  {
    if (newRef == false)
    {
      updateDimensions.push_back(
        Sequence::UpdateInfo(i->first, i->second->_startMap.size()));
    }
    else
    {
      genomeDimensions.push_back(
        Sequence::Info(i->first, i->second->_length, 0,
                       i->second->_startMap.size()));
    }
  }
  if (newRef == false)
  {
    _refGenome->updateBottomDimensions(updateDimensions);
  }
  else
  {
    _refGenome->setDimensions(genomeDimensions);
  }
  if (_refGenome->getNumBottomSegments() > 0)
  {
    _bottomSegment = _refGenome->getBottomSegmentIterator();
    _refBottom = _refGenome->getBottomSegmentIterator();
  }

  // do the child genome dimensions
  curRange = getNextSequences(_dimMap->begin());
  while (curRange.first != _dimMap->end())
  {
    if (curRange != refRange)
    {
      string childName = genomeName(curRange.first->first);
      genomeDimensions.clear();
      for (DimMap::const_iterator i = curRange.first; i != curRange.second; ++i)
      {
        genomeDimensions.push_back(
          Sequence::Info(i->first, i->second->_length,
                         i->second->_startMap.size(), 0));
      }
      Genome* childGenome = _alignment->openGenome(childName);
      assert(childGenome != NULL);

      childGenome->setDimensions(genomeDimensions);
      if (_topSegment.get() == NULL && childGenome->getNumTopSegments() > 0)
      {
        _topSegment = childGenome->getTopSegmentIterator();
      }
    }
    curRange = getNextSequences(curRange.second);
  }

  // update the child idx map
  for (size_t i = 0; i < _refGenome->getNumChildren(); ++i)
  {
    Genome* child = _refGenome->getChild(i);
    _childIdxMap.insert(pair<const Genome*, hal_size_t>(child, i));
  }
}

void MafWriteGenomes::initGenomes()
{
  DNAIteratorPtr dna;
  DNAIteratorConstPtr dnaEnd;
  BottomSegmentIteratorConstPtr bend;
  TopSegmentIteratorConstPtr tend;
  size_t numChildren = _refGenome->getNumChildren();
  if (_refGenome->getSequenceLength() > 0)
  {
    dna = _refGenome->getDNAIterator();
    dnaEnd = _refGenome->getDNAEndIterator();
    while (dna != dnaEnd)
    {
      dna->setChar('N');
      dna->toRight();
    }
    _bottomSegment = _refGenome->getBottomSegmentIterator();
    bend = _refGenome->getBottomSegmentEndIterator();
    while (_bottomSegment != bend)
    {
      for (size_t i = 0; i < numChildren; ++i)
      {
        _bottomSegment->setChildIndex(i, NULL_INDEX);
        _bottomSegment->setChildReversed(i, false);
        _bottomSegment->setTopParseIndex(NULL_INDEX);
      }
    }
  }
  for (size_t i = 0; i < numChildren; ++i)
  {
    Genome* child = _refGenome->getChild(i);
    if (child->getSequenceLength() > 0)
    {
      dna = child->getDNAIterator();
      dnaEnd = child->getDNAEndIterator();
      while (dna != dnaEnd)
      {
        dna->setChar('N');
        dna->toRight();
      }
      _topSegment = child->getTopSegmentIterator();
      tend = child->getTopSegmentEndIterator();
      while (_topSegment != tend)
      {
        _topSegment->setParentIndex(NULL_INDEX);
        _topSegment->setParentReversed(NULL_INDEX);
        _topSegment->setNextParalogyIndex(NULL_INDEX);
        _topSegment->setBottomParseIndex(NULL_INDEX);
      }
    }
  }
}

void MafWriteGenomes::convertBlock()
{
  assert(_rows > 0);
  assert(_block[0]._line.length() == _mask.size());

  for (size_t col = 0; col < _mask.size(); ++col)
  {
    if (_mask[col] == true || col == 0)
    {
      initBlockInfo(col);
      convertSegments(col);
    }
  }
  setBlockEndSegments();
}

void MafWriteGenomes::initBlockInfo(size_t col)
{
  if (col == 0)
  {
    if (_blockInfo.size() < _rows)
    {
      _blockInfo.resize(_rows);
    }
    for (size_t i = 0; i < _rows; ++i)
    {
      _blockInfo[i]._arrayIndex = NULL_INDEX;
      _blockInfo[i]._gaps = 0;
      _blockInfo[i]._start = NULL_INDEX;
      _blockInfo[i]._length = 0;
      assert(_dimMap->find(_block[i]._sequenceName) != _dimMap->end());
      _blockInfo[i]._record = _dimMap->find(_block[i]._sequenceName)->second;
      _blockInfo[i]._genome =
         _alignment->openGenome(genomeName(_block[i]._sequenceName));
      assert(_blockInfo[i]._genome != NULL);
    }
  }
  else
  {
    assert(_blockInfo.size() >= _rows);
  }

  // our range will be [col, last)
  size_t last = col + 1;
  while (last < _mask.size() && _mask[last] == false)
  {
    ++last;
  }

  _refRow = NULL_INDEX;

  for (size_t i = 0; i < _rows; ++i)
  {
    std::string& line = _block[i]._line;
    Row& row = _block[i];
    RowInfo& rowInfo = _blockInfo[i];
    if (line[col] == '-')
    {
      rowInfo._gaps += last - col;
      _blockInfo[i]._start = NULL_INDEX;
      _blockInfo[i]._length = 0;
    }
    else
    {
      rowInfo._start = row._startPosition + col - rowInfo._gaps;
      rowInfo._length = last - col;
      const StartMap& startMap = rowInfo._record->_startMap;
      if (rowInfo._arrayIndex == NULL_INDEX)
      {
        assert(rowInfo._gaps <= col);
        StartMap::const_iterator mapIt = startMap.find(rowInfo._start);
        assert(mapIt != startMap.end());
        rowInfo._arrayIndex = mapIt->second;
        assert(rowInfo._arrayIndex >= 0);
      }
      else
      {
        ++rowInfo._arrayIndex;
        assert(startMap.find(rowInfo._start) != startMap.end());
        assert(startMap.find(rowInfo._start)->second
               == (hal_size_t)rowInfo._arrayIndex);
      }
      if (rowInfo._genome == _refGenome && rowInfo._length > 0 &&
          (_refRow == NULL_INDEX ||
           _block[i]._startPosition < _block[_refRow]._startPosition))
      {
        _refRow = i;
      }
    }
  }
}

void MafWriteGenomes::convertSegments(size_t col)
{
  // do the reference first
  if (_refRow != NULL_INDEX)
  {
    RowInfo& rowInfo = _blockInfo[_refRow];
    Row& row = _block[_refRow];
    _refBottom->setArrayIndex(_refGenome, rowInfo._arrayIndex);
    _refBottom->setCoordinates(rowInfo._start, rowInfo._length);
    _bottomSegment->getSequence()->setSubString(
      row._line.substr(col, rowInfo._length), rowInfo._start, rowInfo._length);
  }

  hal_size_t childIndex;
  for (size_t i = 0; i < _rows; ++i)
  {
    if ((hal_index_t)i != _refRow && _blockInfo[i]._length > 0)
    {
      RowInfo& rowInfo = _blockInfo[i];
      Row& row = _block[i];
      Genome* genome = rowInfo._genome;
      if (genome == _refGenome)
      {
        _bottomSegment->setArrayIndex(rowInfo._genome, rowInfo._arrayIndex);
        _bottomSegment->setCoordinates(rowInfo._start, rowInfo._length);
        _bottomSegment->getSequence()->setSubString(
          row._line.substr(col, rowInfo._length), rowInfo._start,
          rowInfo._length);
      }
      else
      {
        _topSegment->setArrayIndex(rowInfo._genome, rowInfo._arrayIndex);
        _topSegment->setCoordinates(rowInfo._start, rowInfo._length);
        _topSegment->getSequence()->setSubString(
          row._line.substr(col, rowInfo._length), rowInfo._start,
          rowInfo._length);
        if (_refRow != NULL_INDEX)
        {
          childIndex = _childIdxMap.find(rowInfo._genome)->second;
          bool reversed = row._strand != _block[_refRow]._strand;
          _refBottom->setChildIndex(childIndex, rowInfo._arrayIndex);
          _refBottom->setChildReversed(childIndex, reversed);
          _topSegment->setParentIndex(_refBottom->getArrayIndex());
          _topSegment->setParentReversed(reversed);
        }
        else
        {
        }
      }
    }
  }
}

void MafWriteGenomes::setBlockEndSegments()
{
  for (size_t i = 0; i < _rows; ++i)
  {
    RowInfo& rowInfo = _blockInfo[i];
    Row& row = _block[i];

    if (row._length > 0)
    {
      hal_index_t start = row._startPosition + row._length;
      assert(start <= (hal_index_t)row._srcLength);

      if (start < (hal_index_t)row._srcLength)
      {
        const StartMap& startMap = rowInfo._record->_startMap;
        StartMap::const_iterator mapIt = startMap.find(start);
        hal_index_t arrayIndex = mapIt->second;
        ++mapIt;
        if (mapIt != startMap.end())
        {
          hal_index_t length = mapIt->first - start;
          assert(length > 0);
          assert(start + length <= (hal_index_t)row._srcLength);
          if (rowInfo._genome == _refGenome)
          {
            _bottomSegment->setArrayIndex(rowInfo._genome, arrayIndex);
            _bottomSegment->setCoordinates(start, length);
          }
          else
          {
            _topSegment->setArrayIndex(rowInfo._genome, arrayIndex);
            _topSegment->setCoordinates(start, length);
          }
        }
      }
    }
  }
}

void MafWriteGenomes::aLine()
{
  assert(_rows <= _block.size());
  if (_rows > 0)
  {
    convertBlock();
  }
}

void MafWriteGenomes::sLine()
{
  MafScanner::Row& row = _block[_rows-1];

  // CONVERT TO FORWARD COORDINATES
  if (row._strand == '-')
  {
    row._startPosition = row._srcLength - 1 - row._length;
    reverseComplement(row._line);
  }
}

void MafWriteGenomes::end()
{
  assert(_rows <= _block.size());
  if (_rows > 0)
  {
    convertBlock();
  }
}
<commit_msg>fix some bugs in maf import<commit_after>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */
#include <cassert>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <algorithm>
#include "hal.h"
#include "halMafWriteGenomes.h"

using namespace std;
using namespace hal;

MafWriteGenomes::MafWriteGenomes() : MafScanner()
{

}

MafWriteGenomes::~MafWriteGenomes()
{

}

void MafWriteGenomes::convert(const string& mafPath,
                              const string& refGenomeName,
                              const set<string>& targets,
                              const DimMap& dimMap,
                              AlignmentPtr alignment)
{
  _refName = refGenomeName;
  _dimMap = &dimMap;
  _alignment = alignment;
  _topSegment = TopSegmentIteratorPtr();
  _bottomSegment = BottomSegmentIteratorPtr();
  _refBottom = BottomSegmentIteratorPtr();
  _childIdxMap.clear();
  createGenomes();
  initGenomes();
  MafScanner::scan(mafPath, targets);
}

MafWriteGenomes::MapRange MafWriteGenomes::getRefSequences() const
{
  DimMap::const_iterator i = _dimMap->lower_bound(_refName);
  for (; i != _dimMap->end(); ++i)
  {
    if (genomeName(i->first) == _refName)
    {
      break;
    }
  }

  if (i == _dimMap->end())
  {
    stringstream ss;
    ss << "Reference genome " << _refName << " was not found in the MAF file.  "
       "Ie, no sequence in name in the form " << _refName << ".something was "
       "found.";
    throw hal_exception(ss.str());
  }

  DimMap::const_iterator j = i;
  for (; j != _dimMap->end(); ++j)
  {
    if (genomeName(j->first) != _refName)
    {
      break;
    }
  }

  return MapRange(i, j);
}

MafWriteGenomes::MapRange MafWriteGenomes::getNextSequences(
  DimMap::const_iterator jprev) const
{
  DimMap::const_iterator j = jprev;
  if (j == _dimMap->end())
  {
    return MapRange(j, j);
  }
  string name = genomeName(j->first);
  for (; j != _dimMap->end(); ++j)
  {
    if (genomeName(j->first) != name)
    {
      break;
    }
  }
  return MapRange(jprev, j);
}

void MafWriteGenomes::createGenomes()
{
  // need to create the tree before we do anything
  _refGenome = _alignment->openGenome(_refName);
  bool newRef = _refGenome == NULL;
  if (newRef)
  {
    if (_alignment->getNumGenomes() != 0)
    {
      throw hal_exception("Cannot add new reference to non-empty alignment");
    }
    _refGenome = _alignment->addRootGenome(_refName);
  }
  assert(_refGenome != NULL);

  // genomes comprise of ranges of sequences in the map.  do a quick
  // scan to add the children of _refGenome.
  MapRange refRange = getRefSequences();
  MapRange curRange = getNextSequences(_dimMap->begin());
  while (curRange.first != _dimMap->end())
  {
    if (curRange != refRange)
    {
      // note, we do not add a branch length.  will need to add option
      // to maf2hal where a tree can be given as well just for branch lengths
      _alignment->addLeafGenome(genomeName(curRange.first->first), _refName, 1);
    }
    curRange = getNextSequences(curRange.second);
  }

  // do the ref genome dimenions
  vector<Sequence::Info> genomeDimensions;
  vector<Sequence::UpdateInfo> updateDimensions;
  for (DimMap::const_iterator i = refRange.first; i != refRange.second; ++i)
  {
    if (newRef == false)
    {
      updateDimensions.push_back(
        Sequence::UpdateInfo(i->first, i->second->_startMap.size()));
    }
    else
    {
      genomeDimensions.push_back(
        Sequence::Info(i->first, i->second->_length, 0,
                       i->second->_startMap.size()));
    }
  }
  if (newRef == false)
  {
    _refGenome->updateBottomDimensions(updateDimensions);
  }
  else
  {
    _refGenome->setDimensions(genomeDimensions);
  }
  if (_refGenome->getNumBottomSegments() > 0)
  {
    _bottomSegment = _refGenome->getBottomSegmentIterator();
    _refBottom = _refGenome->getBottomSegmentIterator();
  }

  // do the child genome dimensions
  curRange = getNextSequences(_dimMap->begin());
  while (curRange.first != _dimMap->end())
  {
    if (curRange != refRange)
    {
      string childName = genomeName(curRange.first->first);
      genomeDimensions.clear();
      for (DimMap::const_iterator i = curRange.first; i != curRange.second; ++i)
      {
        genomeDimensions.push_back(
          Sequence::Info(i->first, i->second->_length,
                         i->second->_startMap.size(), 0));
      }
      Genome* childGenome = _alignment->openGenome(childName);
      assert(childGenome != NULL);

      childGenome->setDimensions(genomeDimensions);
      if (_topSegment.get() == NULL && childGenome->getNumTopSegments() > 0)
      {
        _topSegment = childGenome->getTopSegmentIterator();
      }
    }
    curRange = getNextSequences(curRange.second);
  }

  // update the child idx map
  for (size_t i = 0; i < _refGenome->getNumChildren(); ++i)
  {
    Genome* child = _refGenome->getChild(i);
    _childIdxMap.insert(pair<const Genome*, hal_size_t>(child, i));
  }
}

void MafWriteGenomes::initGenomes()
{
  DNAIteratorPtr dna;
  DNAIteratorConstPtr dnaEnd;
  BottomSegmentIteratorConstPtr bend;
  TopSegmentIteratorConstPtr tend;
  size_t numChildren = _refGenome->getNumChildren();
  if (_refGenome->getSequenceLength() > 0)
  {
    dna = _refGenome->getDNAIterator();
    dnaEnd = _refGenome->getDNAEndIterator();
    while (dna != dnaEnd)
    {
      dna->setChar('N');
      dna->toRight();
    }
    _bottomSegment = _refGenome->getBottomSegmentIterator();
    bend = _refGenome->getBottomSegmentEndIterator();
    while (_bottomSegment != bend)
    {
      for (size_t i = 0; i < numChildren; ++i)
      {
        _bottomSegment->setChildIndex(i, NULL_INDEX);
        _bottomSegment->setChildReversed(i, false);
        _bottomSegment->setTopParseIndex(NULL_INDEX);
      }
      _bottomSegment->toRight();
    }
  }
  for (size_t i = 0; i < numChildren; ++i)
  {
    Genome* child = _refGenome->getChild(i);
    if (child->getSequenceLength() > 0)
    {
      dna = child->getDNAIterator();
      dnaEnd = child->getDNAEndIterator();
      while (dna != dnaEnd)
      {
        dna->setChar('N');
        dna->toRight();
      }
      _topSegment = child->getTopSegmentIterator();
      tend = child->getTopSegmentEndIterator();
      while (_topSegment != tend)
      {
        _topSegment->setParentIndex(NULL_INDEX);
        _topSegment->setParentReversed(NULL_INDEX);
        _topSegment->setNextParalogyIndex(NULL_INDEX);
        _topSegment->setBottomParseIndex(NULL_INDEX);
        _topSegment->toRight();
      }
    }
  }
}

void MafWriteGenomes::convertBlock()
{
  assert(_rows > 0);
  assert(_block[0]._line.length() == _mask.size());

  for (size_t col = 0; col < _mask.size(); ++col)
  {
    if (_mask[col] == true || col == 0)
    {
      initBlockInfo(col);
      convertSegments(col);
    }
  }
  setBlockEndSegments();
}

void MafWriteGenomes::initBlockInfo(size_t col)
{
  if (col == 0)
  {
    if (_blockInfo.size() < _rows)
    {
      _blockInfo.resize(_rows);
    }
    for (size_t i = 0; i < _rows; ++i)
    {
      _blockInfo[i]._arrayIndex = NULL_INDEX;
      _blockInfo[i]._gaps = 0;
      _blockInfo[i]._start = NULL_INDEX;
      _blockInfo[i]._length = 0;
      assert(_dimMap->find(_block[i]._sequenceName) != _dimMap->end());
      _blockInfo[i]._record = _dimMap->find(_block[i]._sequenceName)->second;
      _blockInfo[i]._genome =
         _alignment->openGenome(genomeName(_block[i]._sequenceName));
      assert(_blockInfo[i]._genome != NULL);
    }
  }
  else
  {
    assert(_blockInfo.size() >= _rows);
  }

  // our range will be [col, last)
  size_t last = col + 1;
  while (last < _mask.size() && _mask[last] == false)
  {
    ++last;
  }

  _refRow = NULL_INDEX;

  for (size_t i = 0; i < _rows; ++i)
  {
    std::string& line = _block[i]._line;
    Row& row = _block[i];
    RowInfo& rowInfo = _blockInfo[i];
    if (line[col] == '-')
    {
      rowInfo._gaps += last - col;
      _blockInfo[i]._start = NULL_INDEX;
      _blockInfo[i]._length = 0;
    }
    else
    {
      rowInfo._start = row._startPosition + col - rowInfo._gaps;
      rowInfo._length = last - col;
      const StartMap& startMap = rowInfo._record->_startMap;
      if (rowInfo._arrayIndex == NULL_INDEX)
      {
        assert(rowInfo._gaps <= col);
        StartMap::const_iterator mapIt = startMap.find(rowInfo._start);
        assert(mapIt != startMap.end());
        rowInfo._arrayIndex = mapIt->second;
        assert(rowInfo._arrayIndex >= 0);
      }
      else
      {
        ++rowInfo._arrayIndex;
        assert(startMap.find(rowInfo._start) != startMap.end());
        assert(startMap.find(rowInfo._start)->second
               == (hal_size_t)rowInfo._arrayIndex);
      }
      if (rowInfo._genome == _refGenome && rowInfo._length > 0 &&
          (_refRow == NULL_INDEX ||
           _block[i]._startPosition < _block[_refRow]._startPosition))
      {
        _refRow = i;
      }
    }
  }
}

void MafWriteGenomes::convertSegments(size_t col)
{
  // do the reference first
  Sequence* seq;
  if (_refRow != NULL_INDEX)
  {
    RowInfo& rowInfo = _blockInfo[_refRow];
    Row& row = _block[_refRow];
    _refBottom->setArrayIndex(_refGenome, rowInfo._arrayIndex);
    seq = _refBottom->getSequence();
    _refBottom->setCoordinates(seq->getStartPosition() + rowInfo._start,
                               rowInfo._length);
    seq->setSubString(
      row._line.substr(col, rowInfo._length), rowInfo._start, rowInfo._length);
  }

  hal_size_t childIndex;
  for (size_t i = 0; i < _rows; ++i)
  {
    if ((hal_index_t)i != _refRow && _blockInfo[i]._length > 0)
    {
      RowInfo& rowInfo = _blockInfo[i];
      Row& row = _block[i];
      Genome* genome = rowInfo._genome;
      if (genome == _refGenome)
      {
        _bottomSegment->setArrayIndex(rowInfo._genome, rowInfo._arrayIndex);
        seq = _bottomSegment->getSequence();
        _bottomSegment->setCoordinates(seq->getStartPosition() + rowInfo._start,
                                       rowInfo._length);
        seq->setSubString(
          row._line.substr(col, rowInfo._length), rowInfo._start,
          rowInfo._length);
      }
      else
      {
        _topSegment->setArrayIndex(rowInfo._genome, rowInfo._arrayIndex);
        seq = _topSegment->getSequence();
        _topSegment->setCoordinates(seq->getStartPosition() + rowInfo._start,
                                    rowInfo._length);
        seq->setSubString(
          row._line.substr(col, rowInfo._length), rowInfo._start,
          rowInfo._length);
        if (_refRow != NULL_INDEX)
        {
          childIndex = _childIdxMap.find(rowInfo._genome)->second;
          bool reversed = row._strand != _block[_refRow]._strand;
          _refBottom->setChildIndex(childIndex, rowInfo._arrayIndex);
          _refBottom->setChildReversed(childIndex, reversed);
          _topSegment->setParentIndex(_refBottom->getArrayIndex());
          _topSegment->setParentReversed(reversed);
        }
        else
        {
        }
      }
    }
  }
}

void MafWriteGenomes::setBlockEndSegments()
{
  for (size_t i = 0; i < _rows; ++i)
  {
    RowInfo& rowInfo = _blockInfo[i];
    Row& row = _block[i];

    if (row._length > 0)
    {
      hal_index_t start = row._startPosition + row._length;
      assert(start <= (hal_index_t)row._srcLength);

      if (start < (hal_index_t)row._srcLength)
      {
        const StartMap& startMap = rowInfo._record->_startMap;
        StartMap::const_iterator mapIt = startMap.find(start);
        hal_index_t arrayIndex = mapIt->second;
        ++mapIt;
        if (mapIt != startMap.end())
        {
          hal_index_t length = mapIt->first - start;
          assert(length > 0);
          assert(start + length <= (hal_index_t)row._srcLength);
          if (rowInfo._genome == _refGenome)
          {
            _bottomSegment->setArrayIndex(rowInfo._genome, arrayIndex);
            Sequence* seq = _bottomSegment->getSequence();
            _bottomSegment->setCoordinates(seq->getStartPosition() + start,
                                           length);
          }
          else
          {
            _topSegment->setArrayIndex(rowInfo._genome, arrayIndex);
            Sequence* seq = _topSegment->getSequence();
            _topSegment->setCoordinates(seq->getStartPosition() + start,
                                        length);
          }
        }
      }
    }
  }
}

void MafWriteGenomes::aLine()
{
  assert(_rows <= _block.size());
  if (_rows > 0)
  {
    convertBlock();
  }
}

void MafWriteGenomes::sLine()
{
  MafScanner::Row& row = _block[_rows-1];

  // CONVERT TO FORWARD COORDINATES
  if (row._strand == '-')
  {
    row._startPosition = row._srcLength - 1 - row._length;
    reverseComplement(row._line);
  }
}

void MafWriteGenomes::end()
{
  assert(_rows <= _block.size());
  if (_rows > 0)
  {
    convertBlock();
  }
}
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    sleep.cxx
// Created: 5/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2010 Tad E. Smith
//
// 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 <log4cplus/config/windowsh-inc.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/timehelper.h>

#include <errno.h>

namespace log4cplus { namespace helpers {

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

int const MILLIS_TO_NANOS = 1000000;
int const SEC_TO_MILLIS = 1000;
DWORD const MAX_SLEEP_SECONDS = (DWORD)4294966;        // (2**32-2)/1000

void
sleep(unsigned long secs, unsigned long nanosecs)
{
#if defined(_WIN32)
    DWORD nano_millis = nanosecs / static_cast<unsigned long>(MILLIS_TO_NANOS);
    if (secs <= MAX_SLEEP_SECONDS) {
        Sleep((secs * SEC_TO_MILLIS) + nano_millis);
        return;
    }

    DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;

    for(DWORD i = 0; i < no_of_max_sleeps; i++) {
        Sleep(MAX_SLEEP_SECONDS * SEC_TO_MILLIS);
    }

    Sleep((secs % MAX_SLEEP_SECONDS) * SEC_TO_MILLIS + nano_millis);
#else
    timespec sleep_time = { secs, nanosecs };
    timespec remain;
    while (nanosleep(&sleep_time, &remain)) {
        if (errno == EINTR) {
            sleep_time.tv_sec  = remain.tv_sec;
            sleep_time.tv_nsec = remain.tv_nsec;
            continue;
        }
        else {
            return;
        }
    }
#endif
}

void
sleepmillis(unsigned long millis)
{
    unsigned long secs = millis / SEC_TO_MILLIS;
    unsigned long nanosecs = (millis % SEC_TO_MILLIS) * MILLIS_TO_NANOS;
    sleep(secs, nanosecs);
}

} } // namespace log4cplus { namespace helpers {
<commit_msg>sleep.cxx: Move MAX_SLEEP_SECONDS into the WIN32 guarded section of code.<commit_after>// Module:  Log4CPLUS
// File:    sleep.cxx
// Created: 5/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2010 Tad E. Smith
//
// 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 <log4cplus/config/windowsh-inc.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/timehelper.h>

#include <errno.h>

namespace log4cplus { namespace helpers {

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

int const MILLIS_TO_NANOS = 1000000;
int const SEC_TO_MILLIS = 1000;

void
sleep(unsigned long secs, unsigned long nanosecs)
{
#if defined(_WIN32)
    DWORD const MAX_SLEEP_SECONDS = 4294966;        // (2**32-2)/1000

    DWORD nano_millis = nanosecs / static_cast<unsigned long>(MILLIS_TO_NANOS);
    if (secs <= MAX_SLEEP_SECONDS) {
        Sleep((secs * SEC_TO_MILLIS) + nano_millis);
        return;
    }

    DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;

    for(DWORD i = 0; i < no_of_max_sleeps; i++) {
        Sleep(MAX_SLEEP_SECONDS * SEC_TO_MILLIS);
    }

    Sleep((secs % MAX_SLEEP_SECONDS) * SEC_TO_MILLIS + nano_millis);
#else
    timespec sleep_time = { secs, nanosecs };
    timespec remain;
    while (nanosleep(&sleep_time, &remain)) {
        if (errno == EINTR) {
            sleep_time.tv_sec  = remain.tv_sec;
            sleep_time.tv_nsec = remain.tv_nsec;
            continue;
        }
        else {
            return;
        }
    }
#endif
}

void
sleepmillis(unsigned long millis)
{
    unsigned long secs = millis / SEC_TO_MILLIS;
    unsigned long nanosecs = (millis % SEC_TO_MILLIS) * MILLIS_TO_NANOS;
    sleep(secs, nanosecs);
}

} } // namespace log4cplus { namespace helpers {
<|endoftext|>


<commit_before>#include <string>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <fstream>
using std::fstream; using std::ifstream; using std::ofstream;

#include <ncurses.h>

#ifdef WIN32 ///For the sleep()
#include <windows.h>	//Sleep(miliseconds);
#else
#include <unistd.h>	//usleep(microseconds);
#endif

class Vector
{
	public:
		Vector() : x(0), y(0){}
		Vector(int x, int y) {setX(x); setY(y);}

		void setX(int x){this->x = x;}
		int getX() const {return this->x;}
		void setY(int y){this->y = y;}
		int getY() const {return this->y;}

		Vector& operator=(const Vector& vec)
		{setX(vec.getX()); setY(vec.getY()); return *this;}
		Vector& operator+=(const Vector& vec)
		{setX(getX()+vec.getX()); setY(getY()+vec.getY()); return *this;}
		Vector operator+(const Vector& vec)
		{Vector v(getX(),getY()); return v+=vec; }
		Vector& operator-=(const Vector& vec)
		{setX(getX()-vec.getX()); setY(getY()-vec.getY()); return *this;}
		Vector operator-(const Vector& vec)
		{Vector v(getX(),getY()); return v-=vec;}
		bool operator==(const Vector& vec)
		{return getX()==vec.getX() && getY()==vec.getY();}
		bool operator!=(const Vector& vec)
		{return !operator==(vec);}

	private:
		int x,y;
};

class Snake
{
	private:
		std::vector<Vector> body;
		Vector apple;
		Vector direction;
		int points;
		int level;
		int best;
		const int height;
		const int width;
		bool exit;
		int speed;
		char* table;
	public:
		Snake(int _height, int _width, int _best)
		: best(_best), height(_height), width(_width)
		{	getApple();
			body.push_back(Vector(width/2, height/2));
			setDirection(0);
			exit=false;
			speed=180;
			level=1;
			points=0;
			srand(time(NULL));
			table = new char[height*width];
		}
		~Snake()
		{delete [] table;}

		void getApple()
		{
			int x = rand()%width;
			int y = rand()%height;
			apple = Vector(x,y);
			for(unsigned int i=0;i<body.size();++i)
				if(apple==body[i])getApple();
		}

		void setDirection(int d)
		{
			switch(d)
			{
				case 0:direction = Vector(0, -1); break;
				case 1:direction = Vector(1, 0); break;
				case 2:direction = Vector(0, 1); break;
				case 3:direction = Vector(-1, 0); break;
			}
		}

		void makeMove()
		{
			exit = false;
			if(body[0].getX()<0 || body[0].getX()>=width)
				exit = true;
			else if(body[0].getX()==0)
			{	if(direction==Vector(-1,0))
					exit = true;
			}
			else if(body[0].getX()==(width-1))
			{	if(direction==Vector(1,0))
					exit = true;
			}

			if(body[0].getY()<0 || body[0].getY()>=height)
				exit = true;
			else if(body[0].getY()==0)
			{
				if(direction==Vector(0,-1))
					exit = true;
			}
			else if(body[0].getY()==(height-1))
			{
				if(direction==Vector(0,1))
					exit = true;
			}

			if(!exit)body[0]+=direction;

			for(unsigned int i = 1; i<body.size(); ++i)
				if(body[i]==body[0]){exit = true; break;}
		}
		void bodyMove()
		{
			for(unsigned int i=body.size()-1; i>0; --i)
				snakeSwap(i);
		}
		void checkForApple()
		{
			if(body[0]==apple)
			{
				points++;
				if(points>best)best = points;
				getApple();
				snakeSwap(body.size());
			}
		}
		void checkPoints()
		{
			switch(points){
				case 10: level = 2; speed = 155; break;
				case 20: level = 3; speed = 130; break;
				case 30: level = 4; speed = 110; break;
				case 40: level = 5; speed = 90; break;
				case 50: level = 6; speed = 80; break;
				case 60: level = 7; speed = 65; break;
				case 70: level = 8; speed = 50; break;
				case 80: level = 9; speed = 40; break;
				case 90: level = 10; speed = 30; break;
				case 100: level = 999; speed = 15; break;
			}
		}
		void snakeSwap(uint i)
		{
			if(i >= body.size())
				body.push_back(body.back());
			else
				body[i] = body[i - 1];
		}
		int getPoints() {return points;}
		int getLevel() {return level;}
		int getBest() {return best;}
		bool getExit() {return exit;}
		void setExit(bool e) {exit = e;}
		int getSpeed() {return speed;}
		int getHeight() {return height;}
		int getWidth() {return width;}
		char* getTable()
		{
			std::memset(table, ' ', height*width);

			table[body[0].getY()*width+body[0].getX()] = 'h';
			for(unsigned int i=1; i<body.size(); ++i)
				table[body[i].getY()*width+body[i].getX()] = 'b';
			table[apple.getY()*width+apple.getX()] = 'a';

			return table;
		}
		int getDirection()
		{
			if(direction.getX()==1)
				return 1;
			else if(direction.getX()==-1)
				return 3;
			else if(direction.getY()==-1)
				return 0;
			else
				return 2;
		}
};

//------------------------------------
int getBest();
void writeBest(int best);
bool writeEndAndGetInput();
void printScore(WINDOW*, int, int, int);
void draw(WINDOW*, Snake&, char*, int, int);
void proccesInput(WINDOW*, Snake&, int);
int main()
{
	initscr();
	noecho();
	cbreak();
	int x,y;
	getmaxyx(stdscr, y, x);
	int best = getBest();
	//render frame
	WINDOW *win = newwin(y-3, x, 1, 0); //height, width, startY, startX
	box(win, 0, 0);
	nodelay(win, TRUE);
	keypad(win, TRUE);

	WINDOW *score = newwin(1, COLS, 0,0);

	//game loop
	do
	{
		Snake snake(y-5, x-2, best);
		refresh();
		wrefresh(win);
		printScore(score, 0, 1, best);
		while(!snake.getExit())
		{
			char *tbl = snake.getTable();
			//process data
			//draw
			draw(win, snake, tbl, snake.getHeight(), snake.getWidth());

			printScore(score, snake.getPoints(), snake.getLevel(), snake.getBest());

			int input = wgetch(win);
			proccesInput(win, snake, input);
			if(snake.getExit())break;

			snake.bodyMove();
			snake.makeMove();
			snake.checkForApple();

			//-----[ SLEEP ]-------
			#ifdef WIN32
			Sleep(snake.getSpeed());
			#else
			usleep(snake.getSpeed() * 1000);
			#endif
			//---------------------
		}
		if(snake.getBest()>best){writeBest(snake.getBest()); best = snake.getBest();}
	}while(writeEndAndGetInput());

	delwin(score);
	delwin(win);
	endwin();
}
std::string getFile()
{
	#ifdef WIN32
	std::string home = "%appdata%/.md.snake\0";
	#else
	std::string home = "~/.md.snake\0";
	#endif
	return home;
}
int getBest()
{
	ifstream fp (getFile().c_str());
	int best = 0;
	std::string content;
	if(fp.is_open() && fp.good())
	{
		getline(fp, content);
		best = strtol(content.c_str(), NULL, 10);
		fp.close();
	}
	return best;
}
void writeBest(int best)
{
	ofstream fp (getFile().c_str());
	if(fp.is_open())
	{
		fp << best;
		fp.close();
	}
}
bool writeEndAndGetInput()
{
	WINDOW* endwin = newwin(2,COLS, LINES-2, 0);
	keypad(endwin, TRUE);
	mvwprintw(endwin, 0, 0, "Press [Spacebar]/[Enter] to play again.");
	mvwprintw(endwin, 1, 0, "Press [q] to quit.");
	int c;
	do{
		c = wgetch(endwin);
	}while(c!=10 && c!=' ' && c!='q' && c!='Q');
	werase(endwin);
	wrefresh(endwin);
	delwin(endwin);
	return (c=='q' || c=='Q')?false:true;
}
void printScore(WINDOW* w, int score, int level, int best)
{
	werase(w);
	mvwprintw(w, 0, 0, "Score: %d", score);
	mvwprintw(w, 0, COLS/2-5, "Level: %d", level);
	mvwprintw(w, 0, COLS-12, "Best: %d", best);
	wrefresh(w);
}
void draw(WINDOW* win, Snake& snake, char* table, int height, int width)
{
	werase(win);
	box(win, 0, 0);
	for(int i=0; i<(height*width); ++i)
	{
		if(table[i]!=' ')
		{
			int y = i/width;
			int x = i-(y*width);
			int ch;
			int d;
			switch(table[i])
			{
				case 'a':
					ch = 'o';
					break;
				case 'h':
					#ifdef WIN32
					d = snake.getDirection();
					if(d==0)ch = ACS_UARROW;
					if(d==1)ch = ACS_RARROW;
					if(d==2)ch = ACS_DARROW;
					if(d==3)ch = ACS_LARROW;
					#else
					ch = '#';
					#endif
					break;
				case 'b':
					ch = '#';
					break;
			}
			mvwaddch(win, 1+y,1+x, ch);
		}
	}
	wrefresh(win);
}
void proccesInput(WINDOW* win, Snake& snake, int input)
{
	int d = snake.getDirection();
	switch(input)
	{
		case KEY_UP:
			if(d!=0 && !(d==2 && snake.getPoints() > 0))
			snake.setDirection(0);
			break;
		case KEY_DOWN:
			if(d!=2 && !(d==0 && snake.getPoints() > 0))
			snake.setDirection(2);
			break;
		case KEY_LEFT:
			if(d!=3 && !(d==1 && snake.getPoints() > 0))
			snake.setDirection(3);
			break;
		case KEY_RIGHT:
			if(d!=1 && !(d==3 && snake.getPoints() > 0))
			snake.setDirection(1);
			break;
		case 'Q':
		case 'q':
			snake.setExit(true);
			break;
		case 'P':
		case 'p':
			char c;
			wattron(win, A_BOLD);
			mvwprintw(win, snake.getHeight()/2, snake.getWidth()/2, "PAUSE");
			wattroff(win, A_BOLD);
			nodelay(win, FALSE);
			do{
				c = wgetch(win);
			}while(c!='p' && c!='P');
			nodelay(win, TRUE);
			break;
	}
}
<commit_msg>Fixed home dir read<commit_after>#include <string>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <fstream>
using std::fstream; using std::ifstream; using std::ofstream;

#include <ncurses.h>

#ifdef WIN32 ///For the sleep()
#include <windows.h>	//Sleep(miliseconds);
#else
#include <unistd.h>	//usleep(microseconds);
#include <sys/types.h>
#include <pwd.h>	//To get home directory
#endif

class Vector
{
	public:
		Vector() : x(0), y(0){}
		Vector(int x, int y) {setX(x); setY(y);}

		void setX(int x){this->x = x;}
		int getX() const {return this->x;}
		void setY(int y){this->y = y;}
		int getY() const {return this->y;}

		Vector& operator=(const Vector& vec)
		{setX(vec.getX()); setY(vec.getY()); return *this;}
		Vector& operator+=(const Vector& vec)
		{setX(getX()+vec.getX()); setY(getY()+vec.getY()); return *this;}
		Vector operator+(const Vector& vec)
		{Vector v(getX(),getY()); return v+=vec; }
		Vector& operator-=(const Vector& vec)
		{setX(getX()-vec.getX()); setY(getY()-vec.getY()); return *this;}
		Vector operator-(const Vector& vec)
		{Vector v(getX(),getY()); return v-=vec;}
		bool operator==(const Vector& vec)
		{return getX()==vec.getX() && getY()==vec.getY();}
		bool operator!=(const Vector& vec)
		{return !operator==(vec);}

	private:
		int x,y;
};

class Snake
{
	private:
		std::vector<Vector> body;
		Vector apple;
		Vector direction;
		int points;
		int level;
		int best;
		const int height;
		const int width;
		bool exit;
		int speed;
		char* table;
	public:
		Snake(int _height, int _width, int _best)
		: best(_best), height(_height), width(_width)
		{	getApple();
			body.push_back(Vector(width/2, height/2));
			setDirection(0);
			exit=false;
			speed=180;
			level=1;
			points=0;
			srand(time(NULL));
			table = new char[height*width];
		}
		~Snake()
		{delete [] table;}

		void getApple()
		{
			int x = rand()%width;
			int y = rand()%height;
			apple = Vector(x,y);
			for(unsigned int i=0;i<body.size();++i)
				if(apple==body[i])getApple();
		}

		void setDirection(int d)
		{
			switch(d)
			{
				case 0:direction = Vector(0, -1); break;
				case 1:direction = Vector(1, 0); break;
				case 2:direction = Vector(0, 1); break;
				case 3:direction = Vector(-1, 0); break;
			}
		}

		void makeMove()
		{
			exit = false;
			if(body[0].getX()<0 || body[0].getX()>=width)
				exit = true;
			else if(body[0].getX()==0)
			{	if(direction==Vector(-1,0))
					exit = true;
			}
			else if(body[0].getX()==(width-1))
			{	if(direction==Vector(1,0))
					exit = true;
			}

			if(body[0].getY()<0 || body[0].getY()>=height)
				exit = true;
			else if(body[0].getY()==0)
			{
				if(direction==Vector(0,-1))
					exit = true;
			}
			else if(body[0].getY()==(height-1))
			{
				if(direction==Vector(0,1))
					exit = true;
			}

			if(!exit)body[0]+=direction;

			for(unsigned int i = 1; i<body.size(); ++i)
				if(body[i]==body[0]){exit = true; break;}
		}
		void bodyMove()
		{
			for(unsigned int i=body.size()-1; i>0; --i)
				snakeSwap(i);
		}
		void checkForApple()
		{
			if(body[0]==apple)
			{
				points++;
				if(points>best)best = points;
				getApple();
				snakeSwap(body.size());
			}
		}
		void checkPoints()
		{
			switch(points){
				case 10: level = 2; speed = 155; break;
				case 20: level = 3; speed = 130; break;
				case 30: level = 4; speed = 110; break;
				case 40: level = 5; speed = 90; break;
				case 50: level = 6; speed = 80; break;
				case 60: level = 7; speed = 65; break;
				case 70: level = 8; speed = 50; break;
				case 80: level = 9; speed = 40; break;
				case 90: level = 10; speed = 30; break;
				case 100: level = 999; speed = 15; break;
			}
		}
		void snakeSwap(uint i)
		{
			if(i >= body.size())
				body.push_back(body.back());
			else
				body[i] = body[i - 1];
		}
		int getPoints() {return points;}
		int getLevel() {return level;}
		int getBest() {return best;}
		bool getExit() {return exit;}
		void setExit(bool e) {exit = e;}
		int getSpeed() {return speed;}
		int getHeight() {return height;}
		int getWidth() {return width;}
		char* getTable()
		{
			std::memset(table, ' ', height*width);

			table[body[0].getY()*width+body[0].getX()] = 'h';
			for(unsigned int i=1; i<body.size(); ++i)
				table[body[i].getY()*width+body[i].getX()] = 'b';
			table[apple.getY()*width+apple.getX()] = 'a';

			return table;
		}
		int getDirection()
		{
			if(direction.getX()==1)
				return 1;
			else if(direction.getX()==-1)
				return 3;
			else if(direction.getY()==-1)
				return 0;
			else
				return 2;
		}
};

//------------------------------------
int getBest();
void writeBest(int best);
bool writeEndAndGetInput();
void printScore(WINDOW*, int, int, int);
void draw(WINDOW*, Snake&, char*, int, int);
void proccesInput(WINDOW*, Snake&, int);
int main()
{
	initscr();
	noecho();
	cbreak();
	int x,y;
	getmaxyx(stdscr, y, x);
	int best = getBest();
	//render frame
	WINDOW *win = newwin(y-3, x, 1, 0); //height, width, startY, startX
	box(win, 0, 0);
	nodelay(win, TRUE);
	keypad(win, TRUE);

	WINDOW *score = newwin(1, COLS, 0,0);

	//game loop
	do
	{
		Snake snake(y-5, x-2, best);
		refresh();
		wrefresh(win);
		printScore(score, 0, 1, best);
		while(!snake.getExit())
		{
			char *tbl = snake.getTable();
			//process data
			//draw
			draw(win, snake, tbl, snake.getHeight(), snake.getWidth());

			printScore(score, snake.getPoints(), snake.getLevel(), snake.getBest());

			int input = wgetch(win);
			proccesInput(win, snake, input);
			if(snake.getExit())break;

			snake.bodyMove();
			snake.makeMove();
			snake.checkForApple();

			//-----[ SLEEP ]-------
			#ifdef WIN32
			Sleep(snake.getSpeed());
			#else
			usleep(snake.getSpeed() * 1000);
			#endif
			//---------------------
		}
		if(snake.getBest()>best){writeBest(snake.getBest()); best = snake.getBest();}
	}while(writeEndAndGetInput());

	delwin(score);
	delwin(win);
	endwin();
}
std::string getFile()
{
	#ifdef WIN32
	std::string home = "%appdata%/.md.snake\0";
	#else
	const char *homedir;

	if ((homedir = getenv("HOME")) == NULL)
	    homedir = getpwuid(getuid())->pw_dir;

	std::string home = std::string(homedir)+"/.md.snake\0";
	#endif
	return home;
}
int getBest()
{
	ifstream fp (getFile().c_str());
	int best = 0;
	std::string content;
	if(fp.is_open() && fp.good())
	{
		getline(fp, content);
		best = strtol(content.c_str(), NULL, 10);
		fp.close();
	}
	return best;
}
void writeBest(int best)
{
	ofstream fp (getFile().c_str());
	if(fp.is_open())
	{
		fp << best;
		fp.close();
	}
}
bool writeEndAndGetInput()
{
	WINDOW* endwin = newwin(2,COLS, LINES-2, 0);
	keypad(endwin, TRUE);
	mvwprintw(endwin, 0, 0, "Press [Spacebar]/[Enter] to play again.");
	mvwprintw(endwin, 1, 0, "Press [q] to quit.");
	int c;
	do{
		c = wgetch(endwin);
	}while(c!=10 && c!=' ' && c!='q' && c!='Q');
	werase(endwin);
	wrefresh(endwin);
	delwin(endwin);
	return (c=='q' || c=='Q')?false:true;
}
void printScore(WINDOW* w, int score, int level, int best)
{
	werase(w);
	mvwprintw(w, 0, 0, "Score: %d", score);
	mvwprintw(w, 0, COLS/2-5, "Level: %d", level);
	mvwprintw(w, 0, COLS-12, "Best: %d", best);
	wrefresh(w);
}
void draw(WINDOW* win, Snake& snake, char* table, int height, int width)
{
	werase(win);
	box(win, 0, 0);
	for(int i=0; i<(height*width); ++i)
	{
		if(table[i]!=' ')
		{
			int y = i/width;
			int x = i-(y*width);
			int ch;
			int d;
			switch(table[i])
			{
				case 'a':
					ch = 'o';
					break;
				case 'h':
					#ifdef WIN32
					d = snake.getDirection();
					if(d==0)ch = ACS_UARROW;
					if(d==1)ch = ACS_RARROW;
					if(d==2)ch = ACS_DARROW;
					if(d==3)ch = ACS_LARROW;
					#else
					ch = '#';
					#endif
					break;
				case 'b':
					ch = '#';
					break;
			}
			mvwaddch(win, 1+y,1+x, ch);
		}
	}
	wrefresh(win);
}
void proccesInput(WINDOW* win, Snake& snake, int input)
{
	int d = snake.getDirection();
	switch(input)
	{
		case KEY_UP:
			if(d!=0 && !(d==2 && snake.getPoints() > 0))
			snake.setDirection(0);
			break;
		case KEY_DOWN:
			if(d!=2 && !(d==0 && snake.getPoints() > 0))
			snake.setDirection(2);
			break;
		case KEY_LEFT:
			if(d!=3 && !(d==1 && snake.getPoints() > 0))
			snake.setDirection(3);
			break;
		case KEY_RIGHT:
			if(d!=1 && !(d==3 && snake.getPoints() > 0))
			snake.setDirection(1);
			break;
		case 'Q':
		case 'q':
			snake.setExit(true);
			break;
		case 'P':
		case 'p':
			char c;
			wattron(win, A_BOLD);
			mvwprintw(win, snake.getHeight()/2, snake.getWidth()/2, "PAUSE");
			wattroff(win, A_BOLD);
			nodelay(win, FALSE);
			do{
				c = wgetch(win);
			}while(c!='p' && c!='P');
			nodelay(win, TRUE);
			break;
	}
}
<|endoftext|>