<commit_before>#include <glow/DebugInfo.h>

#include <sstream>
#include <algorithm>
#include <iomanip>
#include <cassert>

#include <glow/ObjectRegistry.h>
#include <glow/logging.h>
#include <glow/global.h>
#include <glow/memory.h>

#include <glow/Object.h>
#include <glow/Buffer.h>
#include <glow/FrameBufferObject.h>
#include <glow/Program.h>
#include <glow/Query.h>
#include <glow/RenderBufferObject.h>
#include <glow/Sampler.h>
#include <glow/Shader.h>
#include <glow/AbstractStringSource.h>
#include <glow/Texture.h>
#include <glow/TransformFeedback.h>
#include <glow/VertexArrayObject.h>
#include <glow/VertexAttributeBinding.h>
#include <glow/TextureAttachment.h>
#include <glow/RenderBufferAttachment.h>

namespace glow
{

DebugInfo::DebugInfo()
{
}

DebugInfo::~DebugInfo()
{
}

void DebugInfo::printObjectInfo()
{
	print(objectInfo());
}

void DebugInfo::printGeneralInfo()
{
	print(generalInfo());
}

void DebugInfo::printAll()
{
	printGeneralInfo();
	printObjectInfo();
}

void DebugInfo::print(const std::vector<InfoGroup>& info)
{
	for (const InfoGroup& group: info)
	{
		glow::debug() << group.name;

		for (const InfoUnit& unit: group.units)
		{
			glow::debug() << "\t" << unit.name;

			for (const Property& property: unit.properties)
			{
				glow::debug() << "\t\t" << property.name << ": " << property.value;
			}
		}
	}
}

std::vector<DebugInfo::InfoGroup> DebugInfo::generalInfo()
{
	InfoGroup generalGroup;

	InfoUnit generalInfo;
	InfoUnit memoryInfo;
	InfoUnit textureInfo;

	generalGroup.name = "General";

	generalInfo.name = "OpenGL";
	memoryInfo.name = "Memory";
	textureInfo.name = "General Texture Info";

    generalInfo.addProperty("version", versionString());
    generalInfo.addProperty("vendor", vendor());
    generalInfo.addProperty("renderer", renderer());
    generalInfo.addProperty("core profile", isCoreProfile()?"true":"false");
    generalInfo.addProperty("GLSL version", getString(GL_SHADING_LANGUAGE_VERSION));

	memoryInfo.addProperty("total", humanReadableSize(1024ll*memory::total()));
	memoryInfo.addProperty("dedicated", humanReadableSize(1024ll*memory::dedicated()));
	memoryInfo.addProperty("available", humanReadableSize(1024ll*memory::available()));
	memoryInfo.addProperty("evicted", humanReadableSize(1024ll*memory::evicted()));
	memoryInfo.addProperty("evictionCount", memory::evictionCount());

    int maxTextureSize = getInteger(GL_MAX_TEXTURE_SIZE);
	textureInfo.addProperty("Max Texture Size", std::to_string(maxTextureSize)+" x "+std::to_string(maxTextureSize));
    textureInfo.addProperty("Max Vertex Texture Image Units", getInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS));
    textureInfo.addProperty("Max Texture Image Units", getInteger(GL_MAX_IMAGE_UNITS));
    textureInfo.addProperty("Max Geometry Texture Units", getInteger(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS));
    auto maxViewportSize = getIntegers<2>(GL_MAX_VIEWPORT_DIMS);
	textureInfo.addProperty("Max viewport size", std::to_string(maxViewportSize[0])+" x "+std::to_string(maxViewportSize[1]));
    textureInfo.addProperty("Max clip distances", getInteger(GL_MAX_CLIP_DISTANCES));
    textureInfo.addProperty("Max Samples", getInteger(GL_MAX_SAMPLES));

	generalGroup.addInfoUnit(generalInfo);
	generalGroup.addInfoUnit(memoryInfo);
	generalGroup.addInfoUnit(textureInfo);

	return std::vector<InfoGroup>({ generalGroup });
}

std::vector<DebugInfo::InfoGroup> DebugInfo::objectInfo()
{
	DebugInfo debugInfo;
	return debugInfo.collectObjectInfo();
}

std::vector<DebugInfo::InfoGroup> DebugInfo::collectObjectInfo()
{
	m_infoGroups.clear();
	m_memoryUsage.clear();

	for (Object* object: ObjectRegistry::objects())
	{
		visit(object);
	}

	std::vector<InfoGroup> groups;

	InfoGroup overview;
	overview.name = "Overview";
	InfoUnit memory;
	memory.name = "Memory Usage";
	unsigned total = 0;
	for (const std::pair<std::string, unsigned>& pair: m_memoryUsage)
	{
		memory.addProperty(pair.first, humanReadableSize(pair.second));
		total += pair.second;
	}
	memory.addProperty("Total", humanReadableSize(total));
	overview.addInfoUnit(memory);

	groups.push_back(overview);

	for (const std::pair<std::string, InfoGroup>& pair: m_infoGroups)
	{
		groups.push_back(pair.second);
	}

	return groups;
}

void DebugInfo::visitBuffer(Buffer* buffer)
{
    assert(buffer != nullptr);

	InfoUnit info;
	info.name = name("Buffer", buffer);

	GLint memory = buffer->getParameter(GL_BUFFER_SIZE);
	m_memoryUsage["Buffers"] += memory;
	info.addProperty("memory", humanReadableSize(memory));

	addInfo("Buffers", info);
}

void DebugInfo::visitFrameBufferObject(FrameBufferObject* fbo)
{
    assert(fbo != nullptr);

	InfoUnit info;
	info.name = name("FrameBufferObject", fbo);

	for (FrameBufferAttachment* attachment: fbo->attachments())
	{
		std::string objectName;
		if (attachment->isTextureAttachment())
		{
			objectName = name("Texture", dynamic_cast<TextureAttachment*>(attachment)->texture());
		}
		else
		{
			objectName = name("RenderBufferObject", dynamic_cast<RenderBufferAttachment*>(attachment)->renderBuffer());
		}

		info.addProperty(attachment->attachmentString(), objectName);
	}

	addInfo("FrameBufferObjects", info);
}

void DebugInfo::visitProgram(Program* program)
{
    assert(program != nullptr);

	InfoUnit info;
	info.name = name("Program", program);

	GLint memory = program->get(GL_PROGRAM_BINARY_LENGTH);
	m_memoryUsage["Programs"] += memory;
	info.addProperty("memory", humanReadableSize(memory));

	int i = 0;
	for (Shader* shader: program->shaders())
	{
		info.addProperty("Shader "+std::to_string(i++), name("Shader", shader));
	}

	addInfo("Programs", info);
}

void DebugInfo::visitRenderBufferObject(RenderBufferObject* rbo)
{
    assert(rbo != nullptr);

	InfoUnit info;
	info.name = name("RenderBufferObject", rbo);

	int w = rbo->getParameter(GL_RENDERBUFFER_WIDTH);
	int h = rbo->getParameter(GL_RENDERBUFFER_HEIGHT);

	int r = rbo->getParameter(GL_RENDERBUFFER_RED_SIZE);
	int g = rbo->getParameter(GL_RENDERBUFFER_GREEN_SIZE);
	int b = rbo->getParameter(GL_RENDERBUFFER_BLUE_SIZE);
	int a = rbo->getParameter(GL_RENDERBUFFER_ALPHA_SIZE);

	int d = rbo->getParameter(GL_RENDERBUFFER_DEPTH_SIZE);
	int s = rbo->getParameter(GL_RENDERBUFFER_STENCIL_SIZE);

	int memory = (int)std::ceil((w*h*(r+g+b+a+d+s))/8.0);

	m_memoryUsage["RenderBufferObjects"] += memory;
	info.addProperty("memory", humanReadableSize(memory));
	info.addProperty("size", std::to_string(w)+" x "+std::to_string(h));

	addInfo("RenderBufferObjects", info);
}

void DebugInfo::visitSampler(Sampler * sampler)
{
    assert(sampler != nullptr);

    InfoUnit info;
    info.name = name("Sampler", sampler);

    addInfo("Samplers", info);
}

void DebugInfo::visitShader(Shader* shader)
{
    assert(shader != nullptr);

	InfoUnit info;
	info.name = name("Shader", shader);

	info.addProperty("type", shader->typeString());
    if (shader->source() && shader->source()->shortInfo().size() > 0)
	{
        info.addProperty("source", shader->source()->shortInfo());
	}

	addInfo("Shaders", info);
}

void DebugInfo::visitTexture(Texture* texture)
{
    assert(texture != nullptr);

	InfoUnit info;
	info.name = name("Texture", texture);

    int maxTextureSize = getInteger(GL_MAX_TEXTURE_SIZE);
	int maxLevels = (int)std::ceil(std::log(maxTextureSize)/std::log(2))+1;

	int memory = 0;
	for (int i = 0; i<=maxLevels; ++i)
	{
        if (texture->getLevelParameter(i, GL_TEXTURE_COMPRESSED) == GL_TRUE)
		{
			memory += texture->getLevelParameter(i, GL_TEXTURE_COMPRESSED_IMAGE_SIZE);
		}
		else
		{
			int w = texture->getLevelParameter(i, GL_TEXTURE_WIDTH);
			int h = texture->getLevelParameter(i, GL_TEXTURE_HEIGHT);
			int d = texture->getLevelParameter(i, GL_TEXTURE_DEPTH);

			int r = texture->getLevelParameter(i, GL_TEXTURE_RED_SIZE);
			int g = texture->getLevelParameter(i, GL_TEXTURE_GREEN_SIZE);
			int b = texture->getLevelParameter(i, GL_TEXTURE_BLUE_SIZE);
			int a = texture->getLevelParameter(i, GL_TEXTURE_ALPHA_SIZE);
			int ds = texture->getLevelParameter(i, GL_TEXTURE_DEPTH_SIZE);

			memory += (int)std::ceil((w*h*d*(r+g+b+a+ds))/8.0);
		}
	}

	m_memoryUsage["Textures"] += memory;
	info.addProperty("memory", humanReadableSize(memory));
	info.addProperty("size", std::to_string(texture->getLevelParameter(0, GL_TEXTURE_WIDTH))+" x "+std::to_string(texture->getLevelParameter(0, GL_TEXTURE_HEIGHT)));

	addInfo("Textures", info);
}

void DebugInfo::visitTransformFeedback(TransformFeedback* transformfeedback)
{
    assert(transformfeedback != nullptr);

	InfoUnit info;
	info.name = name("TransformFeedback", transformfeedback);

	addInfo("TransformFeedbacks", info);
}

void DebugInfo::visitVertexArrayObject(VertexArrayObject* vao)
{
    assert(vao != nullptr);

	InfoUnit info;
	info.name = name("VertexArrayObject", vao);

	for (VertexAttributeBinding* binding: vao->bindings())
	{
		info.addProperty("binding "+std::to_string(binding->bindingIndex())
            , "location " + std::to_string(binding->attributeIndex())
            + " -> " + name("Buffer", binding->buffer()));
	}

	addInfo("VertexArrayObjects", info);
}

DebugInfo::InfoGroup& DebugInfo::group(const std::string& name)
{
	if (m_infoGroups.find(name) == m_infoGroups.end())
	{
		InfoGroup group;
		group.name = name;
		m_infoGroups[name] = group;
	}

	return m_infoGroups[name];
}

void DebugInfo::addInfo(const std::string& groupName, const InfoUnit& info)
{
	group(groupName).addInfoUnit(info);
}

std::string DebugInfo::humanReadableSize(long long bytes)
{
	if (bytes<0)
	{
		return "n/a";
	}

	static std::vector<char> prefix = { 'k', 'M', 'G', 'T' };
	int power = -1;
	double value = static_cast<double>(bytes);

	std::stringstream ss;

	while (value>=1024.0 && power<static_cast<int>(prefix.size()-1))
	{
		value /= 1024.0;
		power++;
	}

	ss << std::setprecision(3) << value;
	if (power>=0)
	{
		ss << prefix[power];
	}

	ss << "b";

	return ss.str();
}

std::string DebugInfo::name(const std::string& typeName, Object* object)
{
    assert(object != nullptr);

	std::stringstream ss;

	ss << typeName << " (" << object->id();
	if (!object->name().empty()) ss << ", " << object->name();
	ss << ")";

	return ss.str();
}

void DebugInfo::InfoUnit::addProperty(const std::string& name, const std::string& value)
{
	properties.push_back({name, value});
}

void DebugInfo::InfoUnit::addProperty(const std::string& name, GLint value)
{
	addProperty(name, std::to_string(value));
}

void DebugInfo::InfoGroup::addInfoUnit(const InfoUnit& unit)
{
	units.push_back(unit);
}

} // namespace glow
<commit_msg>Add failcheck for cubemaps in DebugInfo<commit_after>#include <glow/DebugInfo.h>

#include <sstream>
#include <algorithm>
#include <iomanip>
#include <cassert>

#include <glow/ObjectRegistry.h>
#include <glow/logging.h>
#include <glow/global.h>
#include <glow/memory.h>

#include <glow/Object.h>
#include <glow/Buffer.h>
#include <glow/FrameBufferObject.h>
#include <glow/Program.h>
#include <glow/Query.h>
#include <glow/RenderBufferObject.h>
#include <glow/Sampler.h>
#include <glow/Shader.h>
#include <glow/AbstractStringSource.h>
#include <glow/Texture.h>
#include <glow/TransformFeedback.h>
#include <glow/VertexArrayObject.h>
#include <glow/VertexAttributeBinding.h>
#include <glow/TextureAttachment.h>
#include <glow/RenderBufferAttachment.h>

namespace glow
{

DebugInfo::DebugInfo()
{
}

DebugInfo::~DebugInfo()
{
}

void DebugInfo::printObjectInfo()
{
	print(objectInfo());
}

void DebugInfo::printGeneralInfo()
{
	print(generalInfo());
}

void DebugInfo::printAll()
{
	printGeneralInfo();
	printObjectInfo();
}

void DebugInfo::print(const std::vector<InfoGroup>& info)
{
	for (const InfoGroup& group: info)
	{
		glow::debug() << group.name;

		for (const InfoUnit& unit: group.units)
		{
			glow::debug() << "\t" << unit.name;

			for (const Property& property: unit.properties)
			{
				glow::debug() << "\t\t" << property.name << ": " << property.value;
			}
		}
	}
}

std::vector<DebugInfo::InfoGroup> DebugInfo::generalInfo()
{
	InfoGroup generalGroup;

	InfoUnit generalInfo;
	InfoUnit memoryInfo;
	InfoUnit textureInfo;

	generalGroup.name = "General";

	generalInfo.name = "OpenGL";
	memoryInfo.name = "Memory";
	textureInfo.name = "General Texture Info";

    generalInfo.addProperty("version", versionString());
    generalInfo.addProperty("vendor", vendor());
    generalInfo.addProperty("renderer", renderer());
    generalInfo.addProperty("core profile", isCoreProfile()?"true":"false");
    generalInfo.addProperty("GLSL version", getString(GL_SHADING_LANGUAGE_VERSION));

	memoryInfo.addProperty("total", humanReadableSize(1024ll*memory::total()));
	memoryInfo.addProperty("dedicated", humanReadableSize(1024ll*memory::dedicated()));
	memoryInfo.addProperty("available", humanReadableSize(1024ll*memory::available()));
	memoryInfo.addProperty("evicted", humanReadableSize(1024ll*memory::evicted()));
	memoryInfo.addProperty("evictionCount", memory::evictionCount());

    int maxTextureSize = getInteger(GL_MAX_TEXTURE_SIZE);
	textureInfo.addProperty("Max Texture Size", std::to_string(maxTextureSize)+" x "+std::to_string(maxTextureSize));
    textureInfo.addProperty("Max Vertex Texture Image Units", getInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS));
    textureInfo.addProperty("Max Texture Image Units", getInteger(GL_MAX_IMAGE_UNITS));
    textureInfo.addProperty("Max Geometry Texture Units", getInteger(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS));
    auto maxViewportSize = getIntegers<2>(GL_MAX_VIEWPORT_DIMS);
	textureInfo.addProperty("Max viewport size", std::to_string(maxViewportSize[0])+" x "+std::to_string(maxViewportSize[1]));
    textureInfo.addProperty("Max clip distances", getInteger(GL_MAX_CLIP_DISTANCES));
    textureInfo.addProperty("Max Samples", getInteger(GL_MAX_SAMPLES));

	generalGroup.addInfoUnit(generalInfo);
	generalGroup.addInfoUnit(memoryInfo);
	generalGroup.addInfoUnit(textureInfo);

	return std::vector<InfoGroup>({ generalGroup });
}

std::vector<DebugInfo::InfoGroup> DebugInfo::objectInfo()
{
	DebugInfo debugInfo;
	return debugInfo.collectObjectInfo();
}

std::vector<DebugInfo::InfoGroup> DebugInfo::collectObjectInfo()
{
	m_infoGroups.clear();
	m_memoryUsage.clear();

	for (Object* object: ObjectRegistry::objects())
	{
		visit(object);
	}

	std::vector<InfoGroup> groups;

	InfoGroup overview;
	overview.name = "Overview";
	InfoUnit memory;
	memory.name = "Memory Usage";
	unsigned total = 0;
	for (const std::pair<std::string, unsigned>& pair: m_memoryUsage)
	{
		memory.addProperty(pair.first, humanReadableSize(pair.second));
		total += pair.second;
	}
	memory.addProperty("Total", humanReadableSize(total));
	overview.addInfoUnit(memory);

	groups.push_back(overview);

	for (const std::pair<std::string, InfoGroup>& pair: m_infoGroups)
	{
		groups.push_back(pair.second);
	}

	return groups;
}

void DebugInfo::visitBuffer(Buffer* buffer)
{
    assert(buffer != nullptr);

	InfoUnit info;
	info.name = name("Buffer", buffer);

	GLint memory = buffer->getParameter(GL_BUFFER_SIZE);
	m_memoryUsage["Buffers"] += memory;
	info.addProperty("memory", humanReadableSize(memory));

	addInfo("Buffers", info);
}

void DebugInfo::visitFrameBufferObject(FrameBufferObject* fbo)
{
    assert(fbo != nullptr);

	InfoUnit info;
	info.name = name("FrameBufferObject", fbo);

	for (FrameBufferAttachment* attachment: fbo->attachments())
	{
		std::string objectName;
		if (attachment->isTextureAttachment())
		{
			objectName = name("Texture", dynamic_cast<TextureAttachment*>(attachment)->texture());
		}
		else
		{
			objectName = name("RenderBufferObject", dynamic_cast<RenderBufferAttachment*>(attachment)->renderBuffer());
		}

		info.addProperty(attachment->attachmentString(), objectName);
	}

	addInfo("FrameBufferObjects", info);
}

void DebugInfo::visitProgram(Program* program)
{
    assert(program != nullptr);

	InfoUnit info;
	info.name = name("Program", program);

	GLint memory = program->get(GL_PROGRAM_BINARY_LENGTH);
	m_memoryUsage["Programs"] += memory;
	info.addProperty("memory", humanReadableSize(memory));

	int i = 0;
	for (Shader* shader: program->shaders())
	{
		info.addProperty("Shader "+std::to_string(i++), name("Shader", shader));
	}

	addInfo("Programs", info);
}

void DebugInfo::visitRenderBufferObject(RenderBufferObject* rbo)
{
    assert(rbo != nullptr);

	InfoUnit info;
	info.name = name("RenderBufferObject", rbo);

	int w = rbo->getParameter(GL_RENDERBUFFER_WIDTH);
	int h = rbo->getParameter(GL_RENDERBUFFER_HEIGHT);

	int r = rbo->getParameter(GL_RENDERBUFFER_RED_SIZE);
	int g = rbo->getParameter(GL_RENDERBUFFER_GREEN_SIZE);
	int b = rbo->getParameter(GL_RENDERBUFFER_BLUE_SIZE);
	int a = rbo->getParameter(GL_RENDERBUFFER_ALPHA_SIZE);

	int d = rbo->getParameter(GL_RENDERBUFFER_DEPTH_SIZE);
	int s = rbo->getParameter(GL_RENDERBUFFER_STENCIL_SIZE);

	int memory = (int)std::ceil((w*h*(r+g+b+a+d+s))/8.0);

	m_memoryUsage["RenderBufferObjects"] += memory;
	info.addProperty("memory", humanReadableSize(memory));
	info.addProperty("size", std::to_string(w)+" x "+std::to_string(h));

	addInfo("RenderBufferObjects", info);
}

void DebugInfo::visitSampler(Sampler * sampler)
{
    assert(sampler != nullptr);

    InfoUnit info;
    info.name = name("Sampler", sampler);

    addInfo("Samplers", info);
}

void DebugInfo::visitShader(Shader* shader)
{
    assert(shader != nullptr);

	InfoUnit info;
	info.name = name("Shader", shader);

	info.addProperty("type", shader->typeString());
    if (shader->source() && shader->source()->shortInfo().size() > 0)
	{
        info.addProperty("source", shader->source()->shortInfo());
	}

	addInfo("Shaders", info);
}

void DebugInfo::visitTexture(Texture* texture)
{
    assert(texture != nullptr);

	InfoUnit info;
	info.name = name("Texture", texture);

    int maxTextureSize = getInteger(GL_MAX_TEXTURE_SIZE);
	int maxLevels = (int)std::ceil(std::log(maxTextureSize)/std::log(2))+1;

    if (texture->target() == GL_TEXTURE_CUBE_MAP)
    {
        info.addProperty("size", "cubemap size computation not implemented yet");
    }
    else
    {
        int memory = 0;
        for (int i = 0; i<=maxLevels; ++i)
        {
            if (texture->getLevelParameter(i, GL_TEXTURE_COMPRESSED) == GL_TRUE)
            {
                memory += texture->getLevelParameter(i, GL_TEXTURE_COMPRESSED_IMAGE_SIZE);
            }
            else
            {
                int w = texture->getLevelParameter(i, GL_TEXTURE_WIDTH);
                int h = texture->getLevelParameter(i, GL_TEXTURE_HEIGHT);
                int d = texture->getLevelParameter(i, GL_TEXTURE_DEPTH);

                int r = texture->getLevelParameter(i, GL_TEXTURE_RED_SIZE);
                int g = texture->getLevelParameter(i, GL_TEXTURE_GREEN_SIZE);
                int b = texture->getLevelParameter(i, GL_TEXTURE_BLUE_SIZE);
                int a = texture->getLevelParameter(i, GL_TEXTURE_ALPHA_SIZE);
                int ds = texture->getLevelParameter(i, GL_TEXTURE_DEPTH_SIZE);

                memory += (int)std::ceil((w*h*d*(r+g+b+a+ds))/8.0);
            }
        }

        m_memoryUsage["Textures"] += memory;
        info.addProperty("memory", humanReadableSize(memory));
        info.addProperty("size", std::to_string(texture->getLevelParameter(0, GL_TEXTURE_WIDTH))+" x "+std::to_string(texture->getLevelParameter(0, GL_TEXTURE_HEIGHT)));
    }

	addInfo("Textures", info);
}

void DebugInfo::visitTransformFeedback(TransformFeedback* transformfeedback)
{
    assert(transformfeedback != nullptr);

	InfoUnit info;
	info.name = name("TransformFeedback", transformfeedback);

	addInfo("TransformFeedbacks", info);
}

void DebugInfo::visitVertexArrayObject(VertexArrayObject* vao)
{
    assert(vao != nullptr);

	InfoUnit info;
	info.name = name("VertexArrayObject", vao);

	for (VertexAttributeBinding* binding: vao->bindings())
	{
		info.addProperty("binding "+std::to_string(binding->bindingIndex())
            , "location " + std::to_string(binding->attributeIndex())
            + " -> " + name("Buffer", binding->buffer()));
	}

	addInfo("VertexArrayObjects", info);
}

DebugInfo::InfoGroup& DebugInfo::group(const std::string& name)
{
	if (m_infoGroups.find(name) == m_infoGroups.end())
	{
		InfoGroup group;
		group.name = name;
		m_infoGroups[name] = group;
	}

	return m_infoGroups[name];
}

void DebugInfo::addInfo(const std::string& groupName, const InfoUnit& info)
{
	group(groupName).addInfoUnit(info);
}

std::string DebugInfo::humanReadableSize(long long bytes)
{
	if (bytes<0)
	{
		return "n/a";
	}

	static std::vector<char> prefix = { 'k', 'M', 'G', 'T' };
	int power = -1;
	double value = static_cast<double>(bytes);

	std::stringstream ss;

	while (value>=1024.0 && power<static_cast<int>(prefix.size()-1))
	{
		value /= 1024.0;
		power++;
	}

	ss << std::setprecision(3) << value;
	if (power>=0)
	{
		ss << prefix[power];
	}

	ss << "b";

	return ss.str();
}

std::string DebugInfo::name(const std::string& typeName, Object* object)
{
    assert(object != nullptr);

	std::stringstream ss;

	ss << typeName << " (" << object->id();
	if (!object->name().empty()) ss << ", " << object->name();
	ss << ")";

	return ss.str();
}

void DebugInfo::InfoUnit::addProperty(const std::string& name, const std::string& value)
{
	properties.push_back({name, value});
}

void DebugInfo::InfoUnit::addProperty(const std::string& name, GLint value)
{
	addProperty(name, std::to_string(value));
}

void DebugInfo::InfoGroup::addInfoUnit(const InfoUnit& unit)
{
	units.push_back(unit);
}

} // namespace glow
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_CUDA_SHARED_HPP__
#define __OPENCV_CUDA_SHARED_HPP__

#include "opencv2/gpu/devmem2d.hpp"
#include "safe_call.hpp"
#include "cuda_runtime.h"

namespace cv
{
    namespace gpu
    {
        typedef unsigned char uchar;
        typedef signed char schar;
        typedef unsigned short ushort;
        typedef unsigned int uint;

        static inline int divUp(int total, int grain) { return (total + grain - 1) / grain; }

        template<class T> static inline void uploadConstant(const char* name, const T& value)
        {
            cudaSafeCall( cudaMemcpyToSymbol(name, &value, sizeof(T)) );
        }

        template<class T> static inline void uploadConstant(const char* name, const T& value, cudaStream_t stream)
        {
            cudaSafeCall( cudaMemcpyToSymbolAsync(name, &value, sizeof(T), 0, cudaMemcpyHostToDevice, stream) );
        }

        template<class T> static inline void bindTexture(const char* name, const DevMem2D_<T>& img/*, bool normalized = false,
            enum cudaTextureFilterMode filterMode = cudaFilterModePoint, enum cudaTextureAddressMode addrMode = cudaAddressModeClamp*/)
        {
            //!!!! const_cast is disabled!
            //!!!! Please use constructor of 'class texture'  instead.

            //textureReference* tex;
            //cudaSafeCall( cudaGetTextureReference((const textureReference**)&tex, name) );
            //tex->normalized = normalized;
            //tex->filterMode = filterMode;
            //tex->addressMode[0] = addrMode;
            //tex->addressMode[1] = addrMode;

            const textureReference* tex;
            cudaSafeCall( cudaGetTextureReference(&tex, name) );

            cudaChannelFormatDesc desc = cudaCreateChannelDesc<T>();
            cudaSafeCall( cudaBindTexture2D(0, tex, img.ptr(), &desc, img.cols, img.rows, img.step) );
        }

        static inline void unbindTexture(const char *name)
        {
            const textureReference* tex;
            cudaSafeCall( cudaGetTextureReference(&tex, name) );
            cudaSafeCall( cudaUnbindTexture(tex) );
        }

        // Available GPU border interpolation modes (named as CPU
        // border interpolation modes)
        enum
        {
            BORDER_REFLECT101 = 0,
        };

    }
}

#endif /* __OPENCV_CUDA_SHARED_HPP__ */
<commit_msg>minor fix in gpu's header<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_CUDA_SHARED_HPP__
#define __OPENCV_CUDA_SHARED_HPP__

#include "opencv2/gpu/devmem2d.hpp"
#include "safe_call.hpp"
#include "cuda_runtime.h"

namespace cv
{
    namespace gpu
    {
        typedef unsigned char uchar;
        typedef signed char schar;
        typedef unsigned short ushort;
        typedef unsigned int uint;

        static inline int divUp(int total, int grain) { return (total + grain - 1) / grain; }

        template<class T> static inline void uploadConstant(const char* name, const T& value)
        {
            cudaSafeCall( cudaMemcpyToSymbol(name, &value, sizeof(T)) );
        }

        template<class T> static inline void uploadConstant(const char* name, const T& value, cudaStream_t stream)
        {
            cudaSafeCall( cudaMemcpyToSymbolAsync(name, &value, sizeof(T), 0, cudaMemcpyHostToDevice, stream) );
        }

        template<class T> static inline void bindTexture(const char* name, const DevMem2D_<T>& img/*, bool normalized = false,
            enum cudaTextureFilterMode filterMode = cudaFilterModePoint, enum cudaTextureAddressMode addrMode = cudaAddressModeClamp*/)
        {
            //!!!! const_cast is disabled!
            //!!!! Please use constructor of 'class texture'  instead.

            //textureReference* tex;
            //cudaSafeCall( cudaGetTextureReference((const textureReference**)&tex, name) );
            //tex->normalized = normalized;
            //tex->filterMode = filterMode;
            //tex->addressMode[0] = addrMode;
            //tex->addressMode[1] = addrMode;

            const textureReference* tex;
            cudaSafeCall( cudaGetTextureReference(&tex, name) );

            cudaChannelFormatDesc desc = cudaCreateChannelDesc<T>();
            cudaSafeCall( cudaBindTexture2D(0, tex, img.ptr(), &desc, img.cols, img.rows, img.step) );
        }

        static inline void unbindTexture(const char *name)
        {
            const textureReference* tex;
            cudaSafeCall( cudaGetTextureReference(&tex, name) );
            cudaSafeCall( cudaUnbindTexture(tex) );
        }

        // Available GPU border interpolation modes (named as CPU
        // border interpolation modes)
        enum
        {
            BORDER_REFLECT101 = 0
        };

    }
}

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


<commit_before>#include "build_helper.h"
#include "gtfs_parser.h"

namespace pt = boost::posix_time;

namespace navimake {
VJ & VJ::frequency(uint32_t start_time, uint32_t end_time, uint32_t headway_secs) {

    uint32_t first_time = vj->stop_time_list.front()->arrival_time;
    for(types::StopTime *st : vj->stop_time_list) {
        st->is_frequency = true;
        st->start_time = start_time+(st->arrival_time - first_time);
        st->end_time = end_time+(st->departure_time - first_time);
        st->headway_secs = headway_secs;
    }

    return *this;

}

VJ::VJ(builder & b, const std::string &line_name, const std::string &validity_pattern, const std::string &block_id, bool wheelchair_boarding, const std::string& uri) : b(b){
    vj = new types::VehicleJourney();
    b.data.vehicle_journeys.push_back(vj);

    auto it = b.lines.find(line_name);
    if(it == b.lines.end()){
        vj->tmp_line = new types::Line();
        vj->tmp_line->uri = line_name;
        b.lines[line_name] = vj->tmp_line;
        vj->tmp_line->name = line_name;
        b.data.lines.push_back(vj->tmp_line);
    } else {
        vj->tmp_line = it->second;
    }

    auto vp_it = b.vps.find(validity_pattern);
    if(vp_it == b.vps.end()){
        vj->validity_pattern = new types::ValidityPattern(b.begin, validity_pattern);
        b.vps[validity_pattern] = vj->validity_pattern;
        b.data.validity_patterns.push_back(vj->validity_pattern);
    } else {
        vj->validity_pattern = vp_it->second;
    }
    vj->block_id = block_id;
    vj->wheelchair_boarding = wheelchair_boarding;
    vj->uri = uri;
    if(!b.data.physical_modes.empty())
        vj->physical_mode = b.data.physical_modes.front();

    if(!b.data.companies.empty())
        vj->company = b.data.companies.front();
}

VJ::VJ(builder & b, const std::string &network_name, const std::string &line_name, const std::string &validity_pattern, const std::string &block_id, bool wheelchair_boarding, const std::string& uri) : b(b){
    VJ(b, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
    vj = b.data.vehicle_journeys.back();
    auto it = b.nts.find(network_name);
    if(it == b.nts.end()){
        vj->tmp_line->network = new types::Network();
        vj->tmp_line->network->uri = network_name;
        vj->tmp_line->network->name = network_name;
        b.nts[network_name] = vj->tmp_line->network;
        b.data.networks.push_back(vj->tmp_line->network);
    } else {
        vj->tmp_line->network = it->second;
    }
}

VJ& VJ::operator()(const std::string &stopPoint, const std::string& arrivee, const std::string& depart,
            uint32_t local_traffic_zone, bool drop_off_allowed, bool pick_up_allowed){
    return (*this)(stopPoint, pt::duration_from_string(arrivee).total_seconds(), pt::duration_from_string(depart).total_seconds(), local_traffic_zone, drop_off_allowed, pick_up_allowed);

}

VJ & VJ::operator()(const std::string & sp_name, int arrivee, int depart, uint32_t local_trafic_zone, bool drop_off_allowed, bool pick_up_allowed){
    types::StopTime * st = new types::StopTime();
    b.data.stops.push_back(st);
    auto it = b.sps.find(sp_name);
    if(it == b.sps.end()){
        st->tmp_stop_point = new types::StopPoint();
        st->tmp_stop_point->name = sp_name;
        st->tmp_stop_point->uri = sp_name;

        if(!b.data.networks.empty())
            st->tmp_stop_point->network = b.data.networks.front();

        b.sps[sp_name] = st->tmp_stop_point;
        b.data.stop_points.push_back(st->tmp_stop_point);
        auto sa_it = b.sas.find(sp_name);
        if(sa_it == b.sas.end()) {
            st->tmp_stop_point->stop_area = new types::StopArea();
            st->tmp_stop_point->stop_area->name = sp_name;
            st->tmp_stop_point->stop_area->uri = sp_name;
            st->tmp_stop_point->stop_area->wheelchair_boarding = true;
            b.sas[sp_name] = st->tmp_stop_point->stop_area;
            b.data.stop_areas.push_back(st->tmp_stop_point->stop_area);
            st->tmp_stop_point->wheelchair_boarding = true;
        } else {
            st->tmp_stop_point->stop_area = sa_it->second;
            st->tmp_stop_point->wheelchair_boarding = st->tmp_stop_point->stop_area->wheelchair_boarding;
        }
    } else {
        st->tmp_stop_point = it->second;
    }

    if(depart == -1) depart = arrivee;
    st->arrival_time = arrivee;
    st->departure_time = depart;
    st->vehicle_journey = vj;
    st->order = vj->stop_time_list.size();
    st->local_traffic_zone = local_trafic_zone;
    st->drop_off_allowed = drop_off_allowed;
    st->pick_up_allowed = pick_up_allowed;
    vj->stop_time_list.push_back(st);
    st->wheelchair_boarding = st->vehicle_journey->wheelchair_boarding;

    return *this;
}

SA::SA(builder & b, const std::string & sa_name, double x, double y, bool wheelchair_boarding) : b(b) {
    sa = new types::StopArea();
    b.data.stop_areas.push_back(sa);
    sa->name = sa_name;
    sa->uri = sa_name;
    sa->coord.set_lon(x);
    sa->coord.set_lat(y);
    sa->wheelchair_boarding = wheelchair_boarding;
    b.sas[sa_name] = sa;
}

SA & SA::operator()(const std::string & sp_name, double x, double y, bool wheelchair_boarding){
    types::StopPoint * sp = new types::StopPoint();
    b.data.stop_points.push_back(sp);
    sp->name = sp_name;
    sp->uri = sp_name;
    sp->wheelchair_boarding = wheelchair_boarding;
    sa->coord.set_lon(x);
    sa->coord.set_lat(y);
    sp->wheelchair_boarding = wheelchair_boarding;
    sp->stop_area = this->sa;
    b.sps[sp_name] = sp;
    return *this;
}

VJ builder::vj(const std::string &line_name, const std::string &validity_pattern, const std::string & block_id, const bool wheelchair_boarding, const std::string& uri){
    return VJ(*this, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
}

VJ builder::vj(const std::string &network_name, const std::string &line_name, const std::string &validity_pattern, const std::string & block_id, const bool wheelchair_boarding, const std::string& uri){
    return VJ(*this, network_name, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
}

SA builder::sa(const std::string &name, double x, double y, const bool wheelchair_boarding){
    return SA(*this, name, x, y, wheelchair_boarding);
}

void builder::connection(const std::string & name1, const std::string & name2, float length) {
    types::Connection * connexion = new types::Connection();
    if(sps.count(name1) == 0 || sps.count(name2) == 0)
        return ;
    connexion->departure_stop_point = (*(sps.find(name1))).second;
    connexion->destination_stop_point = (*(sps.find(name2))).second;

    connexion->connection_kind = types::Connection::LinkConnection;
    connexion->duration = length;

    data.connections.push_back(connexion);

}

 void builder::generate_dummy_basis() {
    types::Country *country = new types::Country();
    this->data.countries.push_back(country);
    country->name = "base_country";
    country->uri = "country:base_country";

    types::District *district = new types::District();
    this->data.districts.push_back(district);
    district->name = "base_district";
    district->uri = "district:base_district";
    district->country = country;

    types::Department *department = new types::Department();
    this->data.departments.push_back(department);
    department->name= "base_department";
    department->uri = "department:base_department";
    department->district = district;

    types::City *city = new types::City();
    this->data.cities.push_back(city);
    city->name = "base_city";
    city->uri = "city:base_city";
    city->department = department;

    types::Company *company = new types::Company();
    this->data.companies.push_back(company);
    company->name = "base_company";
    company->uri = "company:base_company";

    types::Network *network = new types::Network();
    this->data.networks.push_back(network);
    network->name = "base_network";
    network->uri = "network:base_network";

    types::CommercialMode *commercial_mode = new types::CommercialMode();
    commercial_mode->id = "0";
    commercial_mode->name = "Tram";
    commercial_mode->uri = "0x0";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new navimake::types::CommercialMode();
    commercial_mode->id = "1";
    commercial_mode->name = "Metro";
    commercial_mode->uri = "0x1";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "2";
    commercial_mode->name = "Rail";
    commercial_mode->uri = "0x2";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "3";
    commercial_mode->name = "Bus";
    commercial_mode->uri = "0x3";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "4";
    commercial_mode->name = "Ferry";
    commercial_mode->uri = "0x4";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "5";
    commercial_mode->name = "Cable car";
    commercial_mode->uri = "0x5";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "6";
    commercial_mode->name = "Gondola";
    commercial_mode->uri = "0x6";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "7";
    commercial_mode->name = "Funicular";
    commercial_mode->uri = "0x7";
    this->data.commercial_modes.push_back(commercial_mode);

    BOOST_FOREACH(types::CommercialMode *mt, this->data.commercial_modes) {
        types::PhysicalMode* mode = new types::PhysicalMode();
        mode->id = mt->id;
        mode->name = mt->name;
        mode->uri = mt->uri;
        this->data.physical_modes.push_back(mode);
    }

 }

 void builder::build(navitia::type::PT_Data & pt_data) {
    data.normalize_uri();
    data.complete();
    data.clean();
    data.sort();
    data.transform(pt_data);
    pt_data.build_uri();
}

}
<commit_msg>build_helper : modification gestion validitypattern<commit_after>#include "build_helper.h"
#include "gtfs_parser.h"

namespace pt = boost::posix_time;

namespace navimake {
VJ & VJ::frequency(uint32_t start_time, uint32_t end_time, uint32_t headway_secs) {

    uint32_t first_time = vj->stop_time_list.front()->arrival_time;
    for(types::StopTime *st : vj->stop_time_list) {
        st->is_frequency = true;
        st->start_time = start_time+(st->arrival_time - first_time);
        st->end_time = end_time+(st->departure_time - first_time);
        st->headway_secs = headway_secs;
    }

    return *this;

}

VJ::VJ(builder & b, const std::string &line_name, const std::string &validity_pattern, const std::string &block_id, bool wheelchair_boarding, const std::string& uri) : b(b){
    vj = new types::VehicleJourney();
    b.data.vehicle_journeys.push_back(vj);

    auto it = b.lines.find(line_name);
    if(it == b.lines.end()){
        vj->tmp_line = new types::Line();
        vj->tmp_line->uri = line_name;
        b.lines[line_name] = vj->tmp_line;
        vj->tmp_line->name = line_name;
        b.data.lines.push_back(vj->tmp_line);
    } else {
        vj->tmp_line = it->second;
    }

//    auto vp_it = b.vps.find(validity_pattern);
//    if(vp_it == b.vps.end()){
        vj->validity_pattern = new types::ValidityPattern(b.begin, validity_pattern);
        b.vps[validity_pattern] = vj->validity_pattern;
        b.data.validity_patterns.push_back(vj->validity_pattern);
//    } else {
//        vj->validity_pattern = vp_it->second;
//    }
    vj->block_id = block_id;
    vj->wheelchair_boarding = wheelchair_boarding;
    vj->uri = uri;
    if(!b.data.physical_modes.empty())
        vj->physical_mode = b.data.physical_modes.front();

    if(!b.data.companies.empty())
        vj->company = b.data.companies.front();
}

VJ::VJ(builder & b, const std::string &network_name, const std::string &line_name, const std::string &validity_pattern, const std::string &block_id, bool wheelchair_boarding, const std::string& uri) : b(b){
    VJ(b, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
    vj = b.data.vehicle_journeys.back();
    auto it = b.nts.find(network_name);
    if(it == b.nts.end()){
        vj->tmp_line->network = new types::Network();
        vj->tmp_line->network->uri = network_name;
        vj->tmp_line->network->name = network_name;
        b.nts[network_name] = vj->tmp_line->network;
        b.data.networks.push_back(vj->tmp_line->network);
    } else {
        vj->tmp_line->network = it->second;
    }
}

VJ& VJ::operator()(const std::string &stopPoint, const std::string& arrivee, const std::string& depart,
            uint32_t local_traffic_zone, bool drop_off_allowed, bool pick_up_allowed){
    return (*this)(stopPoint, pt::duration_from_string(arrivee).total_seconds(), pt::duration_from_string(depart).total_seconds(), local_traffic_zone, drop_off_allowed, pick_up_allowed);

}

VJ & VJ::operator()(const std::string & sp_name, int arrivee, int depart, uint32_t local_trafic_zone, bool drop_off_allowed, bool pick_up_allowed){
    types::StopTime * st = new types::StopTime();
    b.data.stops.push_back(st);
    auto it = b.sps.find(sp_name);
    if(it == b.sps.end()){
        st->tmp_stop_point = new types::StopPoint();
        st->tmp_stop_point->name = sp_name;
        st->tmp_stop_point->uri = sp_name;

        if(!b.data.networks.empty())
            st->tmp_stop_point->network = b.data.networks.front();

        b.sps[sp_name] = st->tmp_stop_point;
        b.data.stop_points.push_back(st->tmp_stop_point);
        auto sa_it = b.sas.find(sp_name);
        if(sa_it == b.sas.end()) {
            st->tmp_stop_point->stop_area = new types::StopArea();
            st->tmp_stop_point->stop_area->name = sp_name;
            st->tmp_stop_point->stop_area->uri = sp_name;
            st->tmp_stop_point->stop_area->wheelchair_boarding = true;
            b.sas[sp_name] = st->tmp_stop_point->stop_area;
            b.data.stop_areas.push_back(st->tmp_stop_point->stop_area);
            st->tmp_stop_point->wheelchair_boarding = true;
        } else {
            st->tmp_stop_point->stop_area = sa_it->second;
            st->tmp_stop_point->wheelchair_boarding = st->tmp_stop_point->stop_area->wheelchair_boarding;
        }
    } else {
        st->tmp_stop_point = it->second;
    }

    if(depart == -1) depart = arrivee;
    st->arrival_time = arrivee;
    st->departure_time = depart;
    st->vehicle_journey = vj;
    st->order = vj->stop_time_list.size();
    st->local_traffic_zone = local_trafic_zone;
    st->drop_off_allowed = drop_off_allowed;
    st->pick_up_allowed = pick_up_allowed;
    vj->stop_time_list.push_back(st);
    st->wheelchair_boarding = st->vehicle_journey->wheelchair_boarding;

    return *this;
}

SA::SA(builder & b, const std::string & sa_name, double x, double y, bool wheelchair_boarding) : b(b) {
    sa = new types::StopArea();
    b.data.stop_areas.push_back(sa);
    sa->name = sa_name;
    sa->uri = sa_name;
    sa->coord.set_lon(x);
    sa->coord.set_lat(y);
    sa->wheelchair_boarding = wheelchair_boarding;
    b.sas[sa_name] = sa;
}

SA & SA::operator()(const std::string & sp_name, double x, double y, bool wheelchair_boarding){
    types::StopPoint * sp = new types::StopPoint();
    b.data.stop_points.push_back(sp);
    sp->name = sp_name;
    sp->uri = sp_name;
    sp->wheelchair_boarding = wheelchair_boarding;
    sa->coord.set_lon(x);
    sa->coord.set_lat(y);
    sp->wheelchair_boarding = wheelchair_boarding;
    sp->stop_area = this->sa;
    b.sps[sp_name] = sp;
    return *this;
}

VJ builder::vj(const std::string &line_name, const std::string &validity_pattern, const std::string & block_id, const bool wheelchair_boarding, const std::string& uri){
    return VJ(*this, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
}

VJ builder::vj(const std::string &network_name, const std::string &line_name, const std::string &validity_pattern, const std::string & block_id, const bool wheelchair_boarding, const std::string& uri){
    return VJ(*this, network_name, line_name, validity_pattern, block_id, wheelchair_boarding, uri);
}

SA builder::sa(const std::string &name, double x, double y, const bool wheelchair_boarding){
    return SA(*this, name, x, y, wheelchair_boarding);
}

void builder::connection(const std::string & name1, const std::string & name2, float length) {
    types::Connection * connexion = new types::Connection();
    if(sps.count(name1) == 0 || sps.count(name2) == 0)
        return ;
    connexion->departure_stop_point = (*(sps.find(name1))).second;
    connexion->destination_stop_point = (*(sps.find(name2))).second;

    connexion->connection_kind = types::Connection::LinkConnection;
    connexion->duration = length;

    data.connections.push_back(connexion);

}

 void builder::generate_dummy_basis() {
    types::Country *country = new types::Country();
    this->data.countries.push_back(country);
    country->name = "base_country";
    country->uri = "country:base_country";

    types::District *district = new types::District();
    this->data.districts.push_back(district);
    district->name = "base_district";
    district->uri = "district:base_district";
    district->country = country;

    types::Department *department = new types::Department();
    this->data.departments.push_back(department);
    department->name= "base_department";
    department->uri = "department:base_department";
    department->district = district;

    types::City *city = new types::City();
    this->data.cities.push_back(city);
    city->name = "base_city";
    city->uri = "city:base_city";
    city->department = department;

    types::Company *company = new types::Company();
    this->data.companies.push_back(company);
    company->name = "base_company";
    company->uri = "company:base_company";

    types::Network *network = new types::Network();
    this->data.networks.push_back(network);
    network->name = "base_network";
    network->uri = "network:base_network";

    types::CommercialMode *commercial_mode = new types::CommercialMode();
    commercial_mode->id = "0";
    commercial_mode->name = "Tram";
    commercial_mode->uri = "0x0";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new navimake::types::CommercialMode();
    commercial_mode->id = "1";
    commercial_mode->name = "Metro";
    commercial_mode->uri = "0x1";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "2";
    commercial_mode->name = "Rail";
    commercial_mode->uri = "0x2";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "3";
    commercial_mode->name = "Bus";
    commercial_mode->uri = "0x3";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "4";
    commercial_mode->name = "Ferry";
    commercial_mode->uri = "0x4";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "5";
    commercial_mode->name = "Cable car";
    commercial_mode->uri = "0x5";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "6";
    commercial_mode->name = "Gondola";
    commercial_mode->uri = "0x6";
    this->data.commercial_modes.push_back(commercial_mode);

    commercial_mode = new types::CommercialMode();
    commercial_mode->id = "7";
    commercial_mode->name = "Funicular";
    commercial_mode->uri = "0x7";
    this->data.commercial_modes.push_back(commercial_mode);

    BOOST_FOREACH(types::CommercialMode *mt, this->data.commercial_modes) {
        types::PhysicalMode* mode = new types::PhysicalMode();
        mode->id = mt->id;
        mode->name = mt->name;
        mode->uri = mt->uri;
        this->data.physical_modes.push_back(mode);
    }

 }

 void builder::build(navitia::type::PT_Data & pt_data) {
    data.normalize_uri();
    data.complete();
    data.clean();
    data.sort();
    data.transform(pt_data);
    pt_data.build_uri();
}

}
<|endoftext|>


<commit_before>#include "toy/ImageBuffer.hpp"
#include "toy/file/File.hpp"
#include "toy/file/loader/Image.hpp"

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "toy/file/loader/stb/stb_image.h"
#include "toy/file/loader/stb/stb_image_write.h"

namespace toy{
namespace file{

static int ReadImage(void *user,char *data,int size)
{
	auto   dev = static_cast<toy::File*>(user);

	return dev->read(data,size);
}

static void SkipImage(void *user,int n)
{
	auto   dev = static_cast<toy::File*>(user);

	dev->seek(SEEK_CUR,n);
}

static int EndOfFile(void *user)
{
	auto   dev = static_cast<toy::File*>(user);

	return dev->isEnd();
}

bool loader::Load(toy::File *f,ImageBuffer *map)
{
	auto   io = static_cast<void*>(f);

	int32_t      width  = 0;
	int32_t      height = 0;
	int32_t      pixel  = 0;

	stbi_io_callbacks    callback;

	callback.read = ReadImage;
	callback.skip = SkipImage;
	callback.eof  = EndOfFile;

	stbi_set_flip_vertically_on_load(1);    //upside down

	auto   data = stbi_load_from_callbacks( &callback, io, &width, &height, &pixel, STBI_rgb_alpha );

	if ( pixel != 4 )
	{
		toy::Oops(TOY_MARK);
		stbi_image_free(data);
		return false;
	}

	if ( ! image::Create(map,width,height,data) )
	{
		toy::Oops(TOY_MARK);
		stbi_image_free(data);
		return false;
	}

	stbi_image_free(data);

	return true;
}

bool loader::Save(std::string filename,ImageBuffer *map)
{
	stbi_write_tga(filename.c_str(), map->width(), map->height(), 4, map->data());
	return 1;
}

}//namespace file
}//namespace toy

#undef STB_IMAGE_IMPLEMENTATION
#undef STB_IMAGE_WRITE_IMPLEMENTATION
<commit_msg>Support to load RGB format PNG file.<commit_after>#include "toy/ImageBuffer.hpp"
#include "toy/file/File.hpp"
#include "toy/file/loader/Image.hpp"

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "toy/file/loader/stb/stb_image.h"
#include "toy/file/loader/stb/stb_image_write.h"

namespace toy{
namespace file{

static int ReadImage(void *user,char *data,int size)
{
	auto   dev = static_cast<toy::File*>(user);

	return dev->read(data,size);
}

static void SkipImage(void *user,int n)
{
	auto   dev = static_cast<toy::File*>(user);

	dev->seek(SEEK_CUR,n);
}

static int EndOfFile(void *user)
{
	auto   dev = static_cast<toy::File*>(user);

	return dev->isEnd();
}

bool loader::Load(toy::File *f,ImageBuffer *map)
{
	auto   io = static_cast<void*>(f);

	int32_t      width  = 0;
	int32_t      height = 0;
	int32_t      pixel  = 0;

	stbi_io_callbacks    callback;

	callback.read = ReadImage;
	callback.skip = SkipImage;
	callback.eof  = EndOfFile;

	stbi_set_flip_vertically_on_load(1);    //upside down

	auto   data = stbi_load_from_callbacks( &callback, io, &width, &height, &pixel, STBI_default );

	enum toy::Option   fmt = toy::RGBA;

	switch (pixel)
	{
		case 4:
			fmt = toy::RGBA;
			break;
		case 3:
			fmt = toy::RGB;
			break;
		default:
			toy::Oops(TOY_MARK);
			stbi_image_free(data);
			return false;
	}

	if ( ! image::Create(map,width,height,data,fmt) )
	{
		toy::Oops(TOY_MARK);
		stbi_image_free(data);
		return false;
	}

	stbi_image_free(data);

	return true;
}

bool loader::Save(std::string filename,ImageBuffer *map)
{
	stbi_write_tga(filename.c_str(), map->width(), map->height(), 4, map->data());
	return 1;
}

}//namespace file
}//namespace toy

#undef STB_IMAGE_IMPLEMENTATION
#undef STB_IMAGE_WRITE_IMPLEMENTATION
<|endoftext|>


<commit_before>#include "VideoFaceDetector.h"
#include <iostream>
#include <opencv2\imgproc.hpp>

const double VideoFaceDetector::TICK_FREQUENCY = cv::getTickFrequency();

VideoFaceDetector::VideoFaceDetector(const std::string cascadeFilePath, cv::VideoCapture &videoCapture)
{
    setFaceCascade(cascadeFilePath);
    setVideoCapture(videoCapture);
}

void VideoFaceDetector::setVideoCapture(cv::VideoCapture &videoCapture)
{
    m_videoCapture = &videoCapture;
}

cv::VideoCapture *VideoFaceDetector::videoCapture() const
{
    return m_videoCapture;
}

void VideoFaceDetector::setFaceCascade(const std::string cascadeFilePath)
{
    if (m_faceCascade == NULL) {
        m_faceCascade = new cv::CascadeClassifier(cascadeFilePath);
    }
    else {
        m_faceCascade->load(cascadeFilePath);
    }

    if (m_faceCascade->empty()) {
        std::cerr << "Error creating cascade classifier. Make sure the file" << std::endl
            << cascadeFilePath << " exists." << std::endl;
    }
}

cv::CascadeClassifier *VideoFaceDetector::faceCascade() const
{
    return m_faceCascade;
}

void VideoFaceDetector::setResizedWidth(const int width)
{
    m_resizedWidth = std::max(width, 1);
}

int VideoFaceDetector::resizedWidth() const
{
    return m_resizedWidth;
}

cv::Rect VideoFaceDetector::face() const
{
    cv::Rect faceRect = m_trackedFace;
    faceRect.x = (int)(faceRect.x / m_scale);
    faceRect.y = (int)(faceRect.y / m_scale);
    faceRect.width = (int)(faceRect.width / m_scale);
    faceRect.height = (int)(faceRect.height / m_scale);
    return faceRect;
}

cv::Point VideoFaceDetector::facePosition() const
{
    cv::Point facePos;
    facePos.x = (int)(m_facePosition.x / m_scale);
    facePos.y = (int)(m_facePosition.y / m_scale);
    return facePos;
}

void VideoFaceDetector::setTemplateMatchingMaxDuration(const double s)
{
    m_templateMatchingMaxDuration = s;
}

double VideoFaceDetector::templateMatchingMaxDuration() const
{
    return m_templateMatchingMaxDuration;
}

VideoFaceDetector::~VideoFaceDetector()
{
    if (m_faceCascade != NULL) {
        delete m_faceCascade;
    }
}

cv::Rect VideoFaceDetector::doubleRectSize(const cv::Rect &inputRect, const cv::Rect &frameSize) const
{
    cv::Rect outputRect;
    // Double rect size
    outputRect.width = inputRect.width * 2;
    outputRect.height = inputRect.height * 2;

    // Center rect around original center
    outputRect.x = inputRect.x - inputRect.width / 2;
    outputRect.y = inputRect.y - inputRect.height / 2;

    // Handle edge cases
    if (outputRect.x < frameSize.x) {
        outputRect.width += outputRect.x;
        outputRect.x = frameSize.x;
    }
    if (outputRect.y < frameSize.y) {
        outputRect.height += outputRect.y;
        outputRect.y = frameSize.y;
    }

    if (outputRect.x + outputRect.width > frameSize.width) {
        outputRect.width = frameSize.width - outputRect.x;
    }
    if (outputRect.y + outputRect.height > frameSize.height) {
        outputRect.height = frameSize.height - outputRect.y;
    }

    return outputRect;
}

cv::Point VideoFaceDetector::centerOfRect(const cv::Rect &rect) const
{
    return cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
}

cv::Rect VideoFaceDetector::biggestFace(std::vector<cv::Rect> &faces) const
{
    assert(!faces.empty());

    cv::Rect *biggest = &faces[0];
    for (auto &face : faces) {
        if (face.area() < biggest->area())
            biggest = &face;
    }
    return *biggest;
}

/*
* Face template is small patch in the middle of detected face.
*/
cv::Mat VideoFaceDetector::getFaceTemplate(const cv::Mat &frame, cv::Rect face)
{
    face.x += face.width / 4;
    face.y += face.height / 4;
    face.width /= 2;
    face.height /= 2;

    cv::Mat faceTemplate = frame(face).clone();
    return faceTemplate;
}

void VideoFaceDetector::detectFaceAllSizes(const cv::Mat &frame)
{
    // Minimum face size is 1/5th of screen height
    // Maximum face size is 2/3rds of screen height
    m_faceCascade->detectMultiScale(frame, m_allFaces, 1.1, 3, 0,
        cv::Size(frame.rows / 5, frame.rows / 5),
        cv::Size(frame.rows * 2 / 3, frame.rows * 2 / 3));

    if (m_allFaces.empty()) return;

    m_foundFace = true;

    // Locate biggest face
    m_trackedFace = biggestFace(m_allFaces);

    // Copy face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

void VideoFaceDetector::detectFaceAroundRoi(const cv::Mat &frame)
{
    // Detect faces sized +/-20% off biggest face in previous search
    m_faceCascade->detectMultiScale(frame(m_faceRoi), m_allFaces, 1.1, 3, 0,
        cv::Size(m_trackedFace.width * 8 / 10, m_trackedFace.height * 8 / 10),
        cv::Size(m_trackedFace.width * 12 / 10, m_trackedFace.width * 12 / 10));

    if (m_allFaces.empty())
    {
        // Activate template matching if not already started and start timer
        m_templateMatchingRunning = true;
        if (m_templateMatchingStartTime == 0)
            m_templateMatchingStartTime = cv::getTickCount();
        return;
    }

    // Turn off template matching if running and reset timer
    m_templateMatchingRunning = false;
    m_templateMatchingCurrentTime = m_templateMatchingStartTime = 0;

    // Get detected face
    m_trackedFace = biggestFace(m_allFaces);

    // Add roi offset to face
    m_trackedFace.x += m_faceRoi.x;
    m_trackedFace.y += m_faceRoi.y;

    // Get face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

void VideoFaceDetector::detectFacesTemplateMatching(const cv::Mat &frame)
{
    // Calculate duration of template matching
    m_templateMatchingCurrentTime = cv::getTickCount();
    double duration = (double)(m_templateMatchingCurrentTime - m_templateMatchingStartTime) / TICK_FREQUENCY;

    // If template matching lasts for more than 2 seconds face is possibly lost
    // so disable it and redetect using cascades
    if (duration > m_templateMatchingMaxDuration) {
        m_foundFace = false;
        m_templateMatchingRunning = false;
        m_templateMatchingStartTime = m_templateMatchingCurrentTime = 0;
    }

    // Template matching with last known face
    //cv::matchTemplate(frame(m_faceRoi), m_faceTemplate, m_matchingResult, CV_TM_CCOEFF);
    cv::matchTemplate(frame(m_faceRoi), m_faceTemplate, m_matchingResult, CV_TM_SQDIFF_NORMED);
    cv::normalize(m_matchingResult, m_matchingResult, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
    double min, max;
    cv::Point minLoc, maxLoc;
    cv::minMaxLoc(m_matchingResult, &min, &max, &minLoc, &maxLoc);

    // Add roi offset to face position
    minLoc.x += m_faceRoi.x;
    minLoc.y += m_faceRoi.y;

    // Get detected face
    //m_trackedFace = cv::Rect(maxLoc.x, maxLoc.y, m_trackedFace.width, m_trackedFace.height);
    m_trackedFace = cv::Rect(minLoc.x, minLoc.y, m_faceTemplate.cols, m_faceTemplate.rows);
    m_trackedFace = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Get new face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate face roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

cv::Point VideoFaceDetector::getFrameAndDetect(cv::Mat &frame)
{
    *m_videoCapture >> frame;

    // Downscale frame to m_resizedWidth width - keep aspect ratio
    m_scale = (double) std::min(m_resizedWidth, frame.cols) / frame.cols;
    cv::Size resizedFrameSize = cv::Size((int)(m_scale*frame.cols), (int)(m_scale*frame.rows));

    cv::Mat resizedFrame;
    cv::resize(frame, resizedFrame, resizedFrameSize);

    if (!m_foundFace)
        detectFaceAllSizes(resizedFrame); // Detect using cascades over whole image
    else {
        detectFaceAroundRoi(resizedFrame); // Detect using cascades only in ROI
        if (m_templateMatchingRunning) {
            detectFacesTemplateMatching(resizedFrame); // Detect using template matching
        }
    }

    return m_facePosition;
}

cv::Point VideoFaceDetector::operator>>(cv::Mat &frame)
{
    return this->getFrameAndDetect(frame);
}<commit_msg>Fixed crash when faces go of screen while in template matching mode<commit_after>#include "VideoFaceDetector.h"
#include <iostream>
#include <opencv2\imgproc.hpp>

const double VideoFaceDetector::TICK_FREQUENCY = cv::getTickFrequency();

VideoFaceDetector::VideoFaceDetector(const std::string cascadeFilePath, cv::VideoCapture &videoCapture)
{
    setFaceCascade(cascadeFilePath);
    setVideoCapture(videoCapture);
}

void VideoFaceDetector::setVideoCapture(cv::VideoCapture &videoCapture)
{
    m_videoCapture = &videoCapture;
}

cv::VideoCapture *VideoFaceDetector::videoCapture() const
{
    return m_videoCapture;
}

void VideoFaceDetector::setFaceCascade(const std::string cascadeFilePath)
{
    if (m_faceCascade == NULL) {
        m_faceCascade = new cv::CascadeClassifier(cascadeFilePath);
    }
    else {
        m_faceCascade->load(cascadeFilePath);
    }

    if (m_faceCascade->empty()) {
        std::cerr << "Error creating cascade classifier. Make sure the file" << std::endl
            << cascadeFilePath << " exists." << std::endl;
    }
}

cv::CascadeClassifier *VideoFaceDetector::faceCascade() const
{
    return m_faceCascade;
}

void VideoFaceDetector::setResizedWidth(const int width)
{
    m_resizedWidth = std::max(width, 1);
}

int VideoFaceDetector::resizedWidth() const
{
    return m_resizedWidth;
}

cv::Rect VideoFaceDetector::face() const
{
    cv::Rect faceRect = m_trackedFace;
    faceRect.x = (int)(faceRect.x / m_scale);
    faceRect.y = (int)(faceRect.y / m_scale);
    faceRect.width = (int)(faceRect.width / m_scale);
    faceRect.height = (int)(faceRect.height / m_scale);
    return faceRect;
}

cv::Point VideoFaceDetector::facePosition() const
{
    cv::Point facePos;
    facePos.x = (int)(m_facePosition.x / m_scale);
    facePos.y = (int)(m_facePosition.y / m_scale);
    return facePos;
}

void VideoFaceDetector::setTemplateMatchingMaxDuration(const double s)
{
    m_templateMatchingMaxDuration = s;
}

double VideoFaceDetector::templateMatchingMaxDuration() const
{
    return m_templateMatchingMaxDuration;
}

VideoFaceDetector::~VideoFaceDetector()
{
    if (m_faceCascade != NULL) {
        delete m_faceCascade;
    }
}

cv::Rect VideoFaceDetector::doubleRectSize(const cv::Rect &inputRect, const cv::Rect &frameSize) const
{
    cv::Rect outputRect;
    // Double rect size
    outputRect.width = inputRect.width * 2;
    outputRect.height = inputRect.height * 2;

    // Center rect around original center
    outputRect.x = inputRect.x - inputRect.width / 2;
    outputRect.y = inputRect.y - inputRect.height / 2;

    // Handle edge cases
    if (outputRect.x < frameSize.x) {
        outputRect.width += outputRect.x;
        outputRect.x = frameSize.x;
    }
    if (outputRect.y < frameSize.y) {
        outputRect.height += outputRect.y;
        outputRect.y = frameSize.y;
    }

    if (outputRect.x + outputRect.width > frameSize.width) {
        outputRect.width = frameSize.width - outputRect.x;
    }
    if (outputRect.y + outputRect.height > frameSize.height) {
        outputRect.height = frameSize.height - outputRect.y;
    }

    return outputRect;
}

cv::Point VideoFaceDetector::centerOfRect(const cv::Rect &rect) const
{
    return cv::Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
}

cv::Rect VideoFaceDetector::biggestFace(std::vector<cv::Rect> &faces) const
{
    assert(!faces.empty());

    cv::Rect *biggest = &faces[0];
    for (auto &face : faces) {
        if (face.area() < biggest->area())
            biggest = &face;
    }
    return *biggest;
}

/*
* Face template is small patch in the middle of detected face.
*/
cv::Mat VideoFaceDetector::getFaceTemplate(const cv::Mat &frame, cv::Rect face)
{
    face.x += face.width / 4;
    face.y += face.height / 4;
    face.width /= 2;
    face.height /= 2;

    cv::Mat faceTemplate = frame(face).clone();
    return faceTemplate;
}

void VideoFaceDetector::detectFaceAllSizes(const cv::Mat &frame)
{
    // Minimum face size is 1/5th of screen height
    // Maximum face size is 2/3rds of screen height
    m_faceCascade->detectMultiScale(frame, m_allFaces, 1.1, 3, 0,
        cv::Size(frame.rows / 5, frame.rows / 5),
        cv::Size(frame.rows * 2 / 3, frame.rows * 2 / 3));

    if (m_allFaces.empty()) return;

    m_foundFace = true;

    // Locate biggest face
    m_trackedFace = biggestFace(m_allFaces);

    // Copy face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

void VideoFaceDetector::detectFaceAroundRoi(const cv::Mat &frame)
{
    // Detect faces sized +/-20% off biggest face in previous search
    m_faceCascade->detectMultiScale(frame(m_faceRoi), m_allFaces, 1.1, 3, 0,
        cv::Size(m_trackedFace.width * 8 / 10, m_trackedFace.height * 8 / 10),
        cv::Size(m_trackedFace.width * 12 / 10, m_trackedFace.width * 12 / 10));

    if (m_allFaces.empty())
    {
        // Activate template matching if not already started and start timer
        m_templateMatchingRunning = true;
        if (m_templateMatchingStartTime == 0)
            m_templateMatchingStartTime = cv::getTickCount();
        return;
    }

    // Turn off template matching if running and reset timer
    m_templateMatchingRunning = false;
    m_templateMatchingCurrentTime = m_templateMatchingStartTime = 0;

    // Get detected face
    m_trackedFace = biggestFace(m_allFaces);

    // Add roi offset to face
    m_trackedFace.x += m_faceRoi.x;
    m_trackedFace.y += m_faceRoi.y;

    // Get face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

void VideoFaceDetector::detectFacesTemplateMatching(const cv::Mat &frame)
{
    // Calculate duration of template matching
    m_templateMatchingCurrentTime = cv::getTickCount();
    double duration = (double)(m_templateMatchingCurrentTime - m_templateMatchingStartTime) / TICK_FREQUENCY;

    // If template matching lasts for more than 2 seconds face is possibly lost
    // so disable it and redetect using cascades
    if (duration > m_templateMatchingMaxDuration) {
        m_foundFace = false;
        m_templateMatchingRunning = false;
        m_templateMatchingStartTime = m_templateMatchingCurrentTime = 0;
		return;
    }

	// Edge case when face exits frame while
	if (m_faceTemplate.rows * m_faceTemplate.cols == 0) {
		m_foundFace = false;
		m_templateMatchingRunning = false;
		m_templateMatchingStartTime = m_templateMatchingCurrentTime = 0;
		return;
	}

    // Template matching with last known face
    //cv::matchTemplate(frame(m_faceRoi), m_faceTemplate, m_matchingResult, CV_TM_CCOEFF);
    cv::matchTemplate(frame(m_faceRoi), m_faceTemplate, m_matchingResult, CV_TM_SQDIFF_NORMED);
    cv::normalize(m_matchingResult, m_matchingResult, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
    double min, max;
    cv::Point minLoc, maxLoc;
    cv::minMaxLoc(m_matchingResult, &min, &max, &minLoc, &maxLoc);

    // Add roi offset to face position
    minLoc.x += m_faceRoi.x;
    minLoc.y += m_faceRoi.y;

    // Get detected face
    //m_trackedFace = cv::Rect(maxLoc.x, maxLoc.y, m_trackedFace.width, m_trackedFace.height);
    m_trackedFace = cv::Rect(minLoc.x, minLoc.y, m_faceTemplate.cols, m_faceTemplate.rows);
    m_trackedFace = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Get new face template
    m_faceTemplate = getFaceTemplate(frame, m_trackedFace);

    // Calculate face roi
    m_faceRoi = doubleRectSize(m_trackedFace, cv::Rect(0, 0, frame.cols, frame.rows));

    // Update face position
    m_facePosition = centerOfRect(m_trackedFace);
}

cv::Point VideoFaceDetector::getFrameAndDetect(cv::Mat &frame)
{
    *m_videoCapture >> frame;

    // Downscale frame to m_resizedWidth width - keep aspect ratio
    m_scale = (double) std::min(m_resizedWidth, frame.cols) / frame.cols;
    cv::Size resizedFrameSize = cv::Size((int)(m_scale*frame.cols), (int)(m_scale*frame.rows));

    cv::Mat resizedFrame;
    cv::resize(frame, resizedFrame, resizedFrameSize);

    if (!m_foundFace)
        detectFaceAllSizes(resizedFrame); // Detect using cascades over whole image
    else {
        detectFaceAroundRoi(resizedFrame); // Detect using cascades only in ROI
        if (m_templateMatchingRunning) {
            detectFacesTemplateMatching(resizedFrame); // Detect using template matching
        }
    }

    return m_facePosition;
}

cv::Point VideoFaceDetector::operator>>(cv::Mat &frame)
{
    return this->getFrameAndDetect(frame);
}<|endoftext|>


<commit_before>/* Lantern - A path tracer
*
* Lantern is the legal property of Adrian Astley
* Copyright Adrian Astley 2015 - 2016
*/

#include "visualizer/visualizer.h"

#include "renderer/renderer.h"

#include "scene/scene.h"

#include <GLFW/glfw3.h>

#include <imgui.h>
#include <imgui_impl.h>

#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <random>

namespace Lantern {

// Needed for message pump callbacks
Visualizer *g_visualizer;

Visualizer::Visualizer(Renderer *renderer, Scene *scene)
		: m_renderer(renderer),
		  m_scene(scene),
		  m_window(nullptr),
		  m_leftMouseCaptured(false),
		  m_middleMouseCaptured(false) {
	m_tempFrameBuffer = new float3[scene->Camera.FrameBuffer.Width * scene->Camera.FrameBuffer.Height];
	g_visualizer = this;
}

Visualizer::~Visualizer() {
	delete[] m_tempFrameBuffer;
}

static void error_callback(int error, const char *description) {
	printf("Error %d: %s\n", error, description);
}

void Visualizer::Run() {
	Init();

	auto lastRender = std::chrono::high_resolution_clock::now();

	glfwSwapInterval(0);
	while (!glfwWindowShouldClose(m_window)) {
		glfwPollEvents();
		m_imGuiImpl.NewFrame();

		m_renderer->RenderFrame();

		auto currentTime = std::chrono::high_resolution_clock::now();
		int delta = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastRender).count();

		ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiSetCond_FirstUseEver);
		ImGui::Begin("Frame Stats", nullptr, ImVec2(0, 0), -1.0f, ImGuiWindowFlags_AlwaysAutoResize);
		ImGui::Text("%d ms/frame (%.1f FPS)", delta, 1.0f / delta * 1000.0f);
		ImGui::End();

		if (delta >= 0) {
			CopyFrameBufferToGPU();
			lastRender = std::chrono::high_resolution_clock::now();
		}

		// Render scene
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 1.0);
		glVertex2d(-1.0, -1.0);

		glTexCoord2d(1.0, 1.0);
		glVertex2d(1.0, -1.0);

		glTexCoord2d(1.0, 0.0);
		glVertex2d(1.0, 1.0);

		glTexCoord2d(0.0, 0.0);
		glVertex2d(-1.0, 1.0);
		glEnd();

		// Render UI
		ImGui::Render();

		glfwSwapBuffers(m_window);
	}

	Shutdown();
}

void Visualizer::MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
	if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS && mods == GLFW_MOD_ALT) {
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);
		g_visualizer->m_leftMouseCaptured = true;
	} else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
		g_visualizer->m_leftMouseCaptured = false;
	} else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS && mods == GLFW_MOD_ALT) {
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);
		g_visualizer->m_middleMouseCaptured = true;
	} else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) {
		g_visualizer->m_middleMouseCaptured = false;
	}

	g_visualizer->m_imGuiImpl.MouseButtonCallback(window, button, action, mods);
}

void Visualizer::CursorPosCallback(GLFWwindow *window, double xpos, double ypos) {
	if (g_visualizer->m_leftMouseCaptured) {
		double oldX = g_visualizer->m_lastMousePosX;
		double oldY = g_visualizer->m_lastMousePosY;
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);

		g_visualizer->m_scene->Camera.Rotate((float)(oldY - g_visualizer->m_lastMousePosY) / 300,
		                                     (float)(oldX - g_visualizer->m_lastMousePosX) / 300);

		g_visualizer->m_scene->Camera.FrameBuffer.Reset();
	} else if (g_visualizer->m_middleMouseCaptured) {
		double oldX = g_visualizer->m_lastMousePosX;
		double oldY = g_visualizer->m_lastMousePosY;
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);

		g_visualizer->m_scene->Camera.Pan((float)(g_visualizer->m_lastMousePosX - oldX) * 0.01,
		                                  (float)(g_visualizer->m_lastMousePosY - oldY) * 0.01);

		g_visualizer->m_scene->Camera.FrameBuffer.Reset();
	}
}

void Visualizer::ScrollCallback(GLFWwindow *window, double xoffset, double yoffset) {
	g_visualizer->m_scene->Camera.Zoom(yoffset);
	g_visualizer->m_scene->Camera.FrameBuffer.Reset();

	g_visualizer->m_imGuiImpl.ScrollCallback(window, xoffset, yoffset);
}

void Visualizer::KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
	g_visualizer->m_imGuiImpl.KeyCallback(window, key, scancode, action, mods);
}

void Visualizer::CharCallback(GLFWwindow *window, uint c) {
	g_visualizer->m_imGuiImpl.CharCallback(window, c);
}

void Visualizer::Init() {
	// Setup window
	glfwSetErrorCallback(error_callback);
	if (!glfwInit()) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	int width = m_scene->Camera.FrameBuffer.Width;
	int height = m_scene->Camera.FrameBuffer.Height;

	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	GLFWwindow *window = glfwCreateWindow(width, height, "Lantern", nullptr, nullptr);
	m_window = window;

	// Setup ImGui binding
	m_imGuiImpl.InitImpl(window);

	// Bind callbacks
	glfwSetMouseButtonCallback(window, MouseButtonCallback);
	glfwSetCursorPosCallback(window, CursorPosCallback);
	glfwSetScrollCallback(window, ScrollCallback);
	glfwSetKeyCallback(window, KeyCallback);
	glfwSetCharCallback(window, CharCallback);

	// Set up the framebuffer
	glfwMakeContextCurrent(window);
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);

	// Create a texture
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	// Enable textures
	glEnable(GL_TEXTURE_2D);
}

void Visualizer::Shutdown() {
	glfwDestroyWindow(m_window);

	// Cleanup
	m_imGuiImpl.ShutdownImpl();
	glfwTerminate();
}

void Visualizer::CopyFrameBufferToGPU() {
	FrameBuffer *frameBuffer = &m_scene->Camera.FrameBuffer;

	uint width = frameBuffer->Width;
	uint height = frameBuffer->Height;

	float3 *colorData = frameBuffer->GetColorData();
	float *weights = frameBuffer->GetWeights();

	for (uint i = 0; i < width * height; ++i) {
		m_tempFrameBuffer[i] = colorData[i] / weights[i];
	}

	// Update Texture
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, m_tempFrameBuffer);
}

} // End of namespace Lantern
<commit_msg>Correct the camera pan movements<commit_after>/* Lantern - A path tracer
*
* Lantern is the legal property of Adrian Astley
* Copyright Adrian Astley 2015 - 2016
*/

#include "visualizer/visualizer.h"

#include "renderer/renderer.h"

#include "scene/scene.h"

#include <GLFW/glfw3.h>

#include <imgui.h>
#include <imgui_impl.h>

#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <random>

namespace Lantern {

// Needed for message pump callbacks
Visualizer *g_visualizer;

Visualizer::Visualizer(Renderer *renderer, Scene *scene)
		: m_renderer(renderer),
		  m_scene(scene),
		  m_window(nullptr),
		  m_leftMouseCaptured(false),
		  m_middleMouseCaptured(false) {
	m_tempFrameBuffer = new float3[scene->Camera.FrameBuffer.Width * scene->Camera.FrameBuffer.Height];
	g_visualizer = this;
}

Visualizer::~Visualizer() {
	delete[] m_tempFrameBuffer;
}

static void error_callback(int error, const char *description) {
	printf("Error %d: %s\n", error, description);
}

void Visualizer::Run() {
	Init();

	auto lastRender = std::chrono::high_resolution_clock::now();

	glfwSwapInterval(0);
	while (!glfwWindowShouldClose(m_window)) {
		glfwPollEvents();
		m_imGuiImpl.NewFrame();

		m_renderer->RenderFrame();

		auto currentTime = std::chrono::high_resolution_clock::now();
		int delta = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastRender).count();

		ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiSetCond_FirstUseEver);
		ImGui::Begin("Frame Stats", nullptr, ImVec2(0, 0), -1.0f, ImGuiWindowFlags_AlwaysAutoResize);
		ImGui::Text("%d ms/frame (%.1f FPS)", delta, 1.0f / delta * 1000.0f);
		ImGui::End();

		if (delta >= 0) {
			CopyFrameBufferToGPU();
			lastRender = std::chrono::high_resolution_clock::now();
		}

		// Render scene
		glBegin(GL_QUADS);
		glTexCoord2d(0.0, 1.0);
		glVertex2d(-1.0, -1.0);

		glTexCoord2d(1.0, 1.0);
		glVertex2d(1.0, -1.0);

		glTexCoord2d(1.0, 0.0);
		glVertex2d(1.0, 1.0);

		glTexCoord2d(0.0, 0.0);
		glVertex2d(-1.0, 1.0);
		glEnd();

		// Render UI
		ImGui::Render();

		glfwSwapBuffers(m_window);
	}

	Shutdown();
}

void Visualizer::MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
	if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS && mods == GLFW_MOD_ALT) {
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);
		g_visualizer->m_leftMouseCaptured = true;
	} else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
		g_visualizer->m_leftMouseCaptured = false;
	} else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS && mods == GLFW_MOD_ALT) {
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);
		g_visualizer->m_middleMouseCaptured = true;
	} else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) {
		g_visualizer->m_middleMouseCaptured = false;
	}

	g_visualizer->m_imGuiImpl.MouseButtonCallback(window, button, action, mods);
}

void Visualizer::CursorPosCallback(GLFWwindow *window, double xpos, double ypos) {
	if (g_visualizer->m_leftMouseCaptured) {
		double oldX = g_visualizer->m_lastMousePosX;
		double oldY = g_visualizer->m_lastMousePosY;
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);

		g_visualizer->m_scene->Camera.Rotate((float)(oldY - g_visualizer->m_lastMousePosY) / 300,
		                                     (float)(oldX - g_visualizer->m_lastMousePosX) / 300);

		g_visualizer->m_scene->Camera.FrameBuffer.Reset();
	} else if (g_visualizer->m_middleMouseCaptured) {
		double oldX = g_visualizer->m_lastMousePosX;
		double oldY = g_visualizer->m_lastMousePosY;
		glfwGetCursorPos(window, &g_visualizer->m_lastMousePosX, &g_visualizer->m_lastMousePosY);

		g_visualizer->m_scene->Camera.Pan((float)(oldX - g_visualizer->m_lastMousePosX) * 0.01,
		                                  (float)(g_visualizer->m_lastMousePosY - oldY) * 0.01);

		g_visualizer->m_scene->Camera.FrameBuffer.Reset();
	}
}

void Visualizer::ScrollCallback(GLFWwindow *window, double xoffset, double yoffset) {
	g_visualizer->m_scene->Camera.Zoom(yoffset);
	g_visualizer->m_scene->Camera.FrameBuffer.Reset();

	g_visualizer->m_imGuiImpl.ScrollCallback(window, xoffset, yoffset);
}

void Visualizer::KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
	g_visualizer->m_imGuiImpl.KeyCallback(window, key, scancode, action, mods);
}

void Visualizer::CharCallback(GLFWwindow *window, uint c) {
	g_visualizer->m_imGuiImpl.CharCallback(window, c);
}

void Visualizer::Init() {
	// Setup window
	glfwSetErrorCallback(error_callback);
	if (!glfwInit()) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	int width = m_scene->Camera.FrameBuffer.Width;
	int height = m_scene->Camera.FrameBuffer.Height;

	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	GLFWwindow *window = glfwCreateWindow(width, height, "Lantern", nullptr, nullptr);
	m_window = window;

	// Setup ImGui binding
	m_imGuiImpl.InitImpl(window);

	// Bind callbacks
	glfwSetMouseButtonCallback(window, MouseButtonCallback);
	glfwSetCursorPosCallback(window, CursorPosCallback);
	glfwSetScrollCallback(window, ScrollCallback);
	glfwSetKeyCallback(window, KeyCallback);
	glfwSetCharCallback(window, CharCallback);

	// Set up the framebuffer
	glfwMakeContextCurrent(window);
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);

	// Create a texture
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	// Enable textures
	glEnable(GL_TEXTURE_2D);
}

void Visualizer::Shutdown() {
	glfwDestroyWindow(m_window);

	// Cleanup
	m_imGuiImpl.ShutdownImpl();
	glfwTerminate();
}

void Visualizer::CopyFrameBufferToGPU() {
	FrameBuffer *frameBuffer = &m_scene->Camera.FrameBuffer;

	uint width = frameBuffer->Width;
	uint height = frameBuffer->Height;

	float3 *colorData = frameBuffer->GetColorData();
	float *weights = frameBuffer->GetWeights();

	for (uint i = 0; i < width * height; ++i) {
		m_tempFrameBuffer[i] = colorData[i] / weights[i];
	}

	// Update Texture
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, m_tempFrameBuffer);
}

} // End of namespace Lantern
<|endoftext|>