<commit_before>// Copyright (c) 2020 by Apex.AI Inc. All rights reserved.
//
// 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.

#ifndef IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
#define IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP

#include "iceoryx_utils/cxx/string.hpp"
#include "iceoryx_utils/internal/units/duration.hpp"
#include "iceoryx_utils/posix_wrapper/semaphore.hpp"
#include "iceoryx_utils/posix_wrapper/thread.hpp"

#include <thread>

namespace iox
{
namespace concurrent
{
/// @brief This class periodically executes a callable specified by the template parameter.
///        This can be a struct with a `operator()()` overload, a `cxx::function_ref<void()>` or `std::fuction<void()>`
/// @tparam T is a callable type without function parameters
template <typename T>
class PeriodicTask
{
  public:
    /// @brief Creates a periodic task. The specified callable is stored but not executed.
    /// To run the task, `void start(const units::Duration interval)` must be called.
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Creates a periodic task by spawning a thread. The specified callable is executed immediately on creation
    /// and then periodically after the interval duration.
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const units::Duration interval, const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Stops and joins the thread spawned by the constructor.
    /// @note This is blocking and the blocking time depends on the callable.
    ~PeriodicTask() noexcept;

    PeriodicTask(const PeriodicTask&) = delete;
    PeriodicTask(PeriodicTask&&) = delete;

    PeriodicTask& operator=(const PeriodicTask&) = delete;
    PeriodicTask& operator=(PeriodicTask&&) = delete;

    /// @brief Spawns a thread and immediately executes the callable specified with the constructor.
    /// The execution is repeated after the specified interval is passed.
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @attention If there is already a running thread, this will be stopped and started again with the new interval.
    /// This might take some time if a slow task is executing during this call.
    void start(const units::Duration interval) noexcept;

    /// @brief This stops the thread if it's running, otherwise does nothing. When this method returns, the thread is
    /// stopped.
    /// @attention This might take some time if a slow task is executing during this call.
    void stop() noexcept;

    /// @brief This method check if a thread is spawned and running, potentially executing a task.
    /// @return true if the thread is running, false otherwise.
    bool isActive() const noexcept;

  private:
    void run() noexcept;

  private:
    T m_callable;
    posix::ThreadName_t m_taskName;
    units::Duration m_interval{units::Duration::milliseconds<long double>(0.0)};
    /// @todo use a refactored posix::Timer object once available
    posix::Semaphore m_stop{posix::Semaphore::create(posix::CreateUnnamedSingleProcessSemaphore, 0U).value()};
    std::thread m_taskExecutor;
};

} // namespace concurrent
} // namespace iox

#include "iceoryx_utils/internal/concurrent/periodic_task.inl"

#endif // IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
<commit_msg>iox-#489 Update PeriodicTask documentation<commit_after>// Copyright (c) 2020 by Apex.AI Inc. All rights reserved.
//
// 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.

#ifndef IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
#define IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP

#include "iceoryx_utils/cxx/string.hpp"
#include "iceoryx_utils/internal/units/duration.hpp"
#include "iceoryx_utils/posix_wrapper/semaphore.hpp"
#include "iceoryx_utils/posix_wrapper/thread.hpp"

#include <thread>

namespace iox
{
namespace concurrent
{
/// @brief This class periodically executes a callable specified by the template parameter.
///        This can be a struct with a `operator()()` overload, a `cxx::function_ref<void()>` or `std::fuction<void()>`
/// @tparam T is a callable type without function parameters
template <typename T>
class PeriodicTask
{
  public:
    /// @brief Creates a periodic task. The specified callable is stored but not executed.
    /// To run the task, `void start(const units::Duration interval)` must be called.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Creates a periodic task by spawning a thread. The specified callable is executed immediately on creation
    /// and then periodically after the interval duration.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const units::Duration interval, const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Stops and joins the thread spawned by the constructor.
    /// @note This is blocking and the blocking time depends on the callable.
    ~PeriodicTask() noexcept;

    PeriodicTask(const PeriodicTask&) = delete;
    PeriodicTask(PeriodicTask&&) = delete;

    PeriodicTask& operator=(const PeriodicTask&) = delete;
    PeriodicTask& operator=(PeriodicTask&&) = delete;

    /// @brief Spawns a thread and immediately executes the callable specified with the constructor.
    /// The execution is repeated after the specified interval is passed.
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @attention If the PeriodicTask instance has already a running thread, this will be stopped and started again
    /// with the new interval. This might take some time if a slow task is executing during this call.
    void start(const units::Duration interval) noexcept;

    /// @brief This stops the thread if it's running, otherwise does nothing. When this method returns, the thread is
    /// stopped.
    /// @attention This might take some time if a slow task is executing during this call.
    void stop() noexcept;

    /// @brief This method check if a thread is spawned and running, potentially executing a task.
    /// @return true if the thread is running, false otherwise.
    bool isActive() const noexcept;

  private:
    void run() noexcept;

  private:
    T m_callable;
    posix::ThreadName_t m_taskName;
    units::Duration m_interval{units::Duration::milliseconds<long double>(0.0)};
    /// @todo use a refactored posix::Timer object once available
    posix::Semaphore m_stop{posix::Semaphore::create(posix::CreateUnnamedSingleProcessSemaphore, 0U).value()};
    std::thread m_taskExecutor;
};

} // namespace concurrent
} // namespace iox

#include "iceoryx_utils/internal/concurrent/periodic_task.inl"

#endif // IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
<|endoftext|>


<commit_before>#include "Application.h"
#include "../Libraries/picopng/picopng.h"
#include "../Libraries/triggmath/triggmath.h"
#include "../Engine/FileHelper.h"

#include "../Engine/WindowObject.h"

Application::Application()
{
}

Application::~Application()
{
	delete Window;
}

void Application::Init()
{
	Window = new WindowObject();
	Window->CreateConsole();
	Window->SetConsoleTitle("PNG2SignedDistanceMap by Haydn Trigg 2014");

	// Welcome Message
	Console::Out << (Console::Colors::ConsoleColor)(Console::Colors::CMD_LIGHTBLUEMAJOR + Console::Colors::CMD_WHITEMINOR) <<
		"PNG2SignedDistanceMap v1.0.1 written by Haydn Trigg\n" << Console::Colors::Text <<
		"Please input filename: ";
	string filename;
	bool file_exists = false;
	std::cin >> filename;
	while (!file_exists)
	{
		if (filename == "q") exit(0);
		else file_exists = FileHelper::FileExists(filename);
		if (file_exists) Console::Out << Console::Colors::Success << "PNG File Exists! " << "[" << filename << "]\n";
		else
		{
			Console::Out << Console::Colors::Error << "PNG Does Not Exist! Please try again...\n" << "Please input filename: ";
			std::cin >> filename;
		}
	}

	Console::Out << "Input Kernel Size: ";
	int kernel_size = 0;
	string kernel_string;

	while (kernel_size <= 0)
	{
		std::cin >> kernel_string;
		if (kernel_string == "q") exit(0);
		else
		{
			try
			{
				kernel_size = atoi(kernel_string.c_str());
			}
			catch (void*)
			{
				Console::OutLn << Console::Colors::Error << "Please input a number!";
				kernel_size = 0;
			}
		}

		if (kernel_size > 0)
		{
			Console::Out << Console::Colors::Success << "Kernel Size " << "[" << kernel_size << "]\n";
			break;
		}
		else
		{
			Console::Out << Console::Colors::Error << "Kernel Size must be greater than zero!\n" << "Please input Kernel Size: ";
		}
	}

	string out_filename;
	bool out_filename_created = false;
	while (!out_filename_created)
	{
		Console::Out << "Input Output Filename: ";
		std::cin >> out_filename;
		if (filename == "q") exit(0);
		else file_exists = FileHelper::FileExists(out_filename);

		if (file_exists)
		{
			Console::Out << Console::Colors::Text << "File Exists! Overwrite [Y/N]" << "[" << filename << "]\n";
			string answer;
			std::cin >> answer;
			out_filename_created = (answer == "Y" || answer == "y");
		}
		else out_filename_created = true;
	}
	Console::Out << Console::Colors::Success << "File Output Name:" << "[" << out_filename << "]\n";

	picopng::PNG png(filename);
	float searchDistance = (float)kernel_size;

	if (png.Width > 0 && png.Height > 0 && png.Data.size() > 0)
	{
		size_t png_data_size = png.Data.size();

		std::vector<float> distance_data;
		distance_data.resize(png_data_size / 4);

		float init = (float)sqrt((double)(png.Width*png.Width + png.Height*png.Height));
		float max = 0.0f;
		const float min = 0.0f;
		Console::Out << "Completed: " << 0 << "/" << png.Width << "\n";
		unsigned long long last_time = GetTickCount64();
		float delta = 0;

		for (unsigned int i = 0; i < png.Width; i++) //0
		{
			for (unsigned int j = 0; j < png.Height; j++) //1
			{
				float *output = &distance_data[i + j * png.Width];
				*output = init;
				unsigned char data = png.Data[4 * (i + j * png.Width)]; // Get the Data

				if (data <= 0)
				{
					for (unsigned int k = 0; k < png.Width; k++)
					{
						for (unsigned int w = 0; w < png.Height; w++) //2 & 3
						{
							unsigned char data = png.Data[4 * (k + w * png.Width)]; // Get the Data
							if (data > 0)
							{
								// Calculate distance and maintain maximum precision
								long long x_dist = (long long)i - k;
								long long y_dist = (long long)j - w;
								float distance = (float)sqrt((double)(x_dist*x_dist + y_dist*y_dist));

								if (distance < *output) *output = distance;
								if (distance > max) max = distance;
								//if (distance < min) min = distance;

								if (*output <= 1) break;;
							}
						}
						if (*output <= 1) break;;
					}
				}
				else *output = 0;
			}

			unsigned long long current_time = GetTickCount64();
			unsigned long long delta_time = current_time - last_time;
			last_time = current_time;
			float f_delta_time = (float)((double)delta_time / 1000);
			float more_ticks = (float)(png.Width - i);
			if (i == 0) delta = f_delta_time;
			delta = (delta * 2 + f_delta_time) / 3.0f;
			float remaning_time = delta * more_ticks;

			Console::Clear();
			Console::Out << "Completed: " << i + 1 << "/" << png.Width << "Remaning: " << (int)remaning_time << "secs \n";
		}

		FileHelper::FreeVector(png.Data);

		// : Convert data into 0-1 byte data :
		float divisor = max - min;
		std::vector<unsigned char> texture_data;
		texture_data.resize(png_data_size / 4);

		for (unsigned int i = 0; i < png.Width; i++) for (unsigned int j = 0; j < png.Height; j++)
		{
			float value = distance_data[i + j*png.Width];

			// Clamp distance to -/+
			value = Math::Clamp(value, -searchDistance, +searchDistance);

			// Convert from -search,+search to 0,+search*2 and then convert to 0.0, 1.0 and invert
			value = 1.0f - Math::Clamp((value + searchDistance) / (searchDistance + searchDistance), 0, 1);

			texture_data[i + (png.Height - j - 1)*png.Width] = (unsigned char)(value*255.0f);
		}

		FileHelper::FreeVector(distance_data);

		// : Create Bitmap Pixel Data
		std::vector<Pixel> bmp_data;
		bmp_data.resize(texture_data.size());
		for (unsigned int i = 0; i < png.Width; i++) for (unsigned int j = 0; j < png.Height; j++)
		{
			unsigned char data = texture_data[i + j*png.Width];
			bmp_data[i + j*png.Width].r = data;
			bmp_data[i + j*png.Width].g = data;
			bmp_data[i + j*png.Width].b = data;
		}

		FileHelper::FreeVector(texture_data);

		if (SaveBMP((unsigned char*)(&bmp_data[0]), bmp_data.size() * 3, png.Width, png.Height, (char*)out_filename.c_str()))
		{
			Console::Out << Console::Colors::Success << "Process Complete: " << "Saved to " << "[" << out_filename << "]\n";
		}
		else Console::Out << Console::Colors::Error << "Process Failed: " << "Could not save output file!\n";

		system("pause");
	}
}

bool Application::SaveBMP(unsigned char* data, DWORD data_size, int width, int height, char* filepath)
{
	BITMAPFILEHEADER bmfh;
	BITMAPINFOHEADER info;
	memset(&bmfh, 0, sizeof (BITMAPFILEHEADER));
	memset(&info, 0, sizeof (BITMAPINFOHEADER));

	bmfh.bfType = 0x4d42;       // 0x4d42 = 'BM'
	bmfh.bfReserved1 = 0;
	bmfh.bfReserved2 = 0;
	bmfh.bfSize = sizeof(BITMAPFILEHEADER)+
		sizeof(BITMAPINFOHEADER)+data_size;
	bmfh.bfOffBits = 0x36;

	info.biSize = sizeof(BITMAPINFOHEADER);
	info.biWidth = width;
	info.biHeight = height;
	info.biPlanes = 1;
	info.biBitCount = 24;
	info.biCompression = BI_RGB;
	info.biSizeImage = 0;
	info.biXPelsPerMeter = 0x0ec4;
	info.biYPelsPerMeter = 0x0ec4;
	info.biClrUsed = 0;
	info.biClrImportant = 0;

	HANDLE file = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_READ,
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (NULL == file)
	{
		CloseHandle(file);
		return false;
	}

	unsigned long bwritten;
	if (WriteFile(file, &bmfh, sizeof (BITMAPFILEHEADER),
		&bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	if (WriteFile(file, &info, sizeof (BITMAPINFOHEADER),
		&bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	if (WriteFile(file, data, data_size, &bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	CloseHandle(file);
	return true;
}<commit_msg>Performance Improvement, Notifications and Clean-up<commit_after>#include "Application.h"
#include "../Libraries/picopng/picopng.h"
#include "../Libraries/triggmath/triggmath.h"
#include "../Engine/FileHelper.h"

#include "../Engine/WindowObject.h"

Application::Application()
{
}

Application::~Application()
{
	delete Window;
}

void Application::Init()
{
	Window = new WindowObject();
	Window->CreateConsole();
	Window->SetConsoleTitle("PNG2SignedDistanceMap");

	// Welcome Message
	Console::Out << (Console::Colors::ConsoleColor)(Console::Colors::CMD_LIGHTBLUEMAJOR + Console::Colors::CMD_WHITEMINOR) <<
		"PNG2SignedDistanceMap v1.0.2 written by Haydn Trigg\n" << Console::Colors::Text <<
		"Please input filename: ";

	// :: Source File ::
	string filename;
	bool file_exists = false;
	std::cin >> filename;
	while (!file_exists)
	{
		if (filename == "q") exit(0);
		else file_exists = FileHelper::FileExists(filename);
		if (file_exists) Console::Out << Console::Colors::Success << "PNG File Exists! " << "[" << filename << "]\n";
		else
		{
			Console::Out << Console::Colors::Error << "PNG Does Not Exist! Please try again...\n" << "Please input filename: ";
			std::cin >> filename;
		}
	}

	// :: Kernel Size ::
	Console::Out << "Input Kernel Size: ";
	int kernel_size = 0;
	string kernel_string;

	while (kernel_size <= 0)
	{
		std::cin >> kernel_string;
		if (kernel_string == "q") exit(0);
		else
		{
			try
			{
				kernel_size = atoi(kernel_string.c_str());
			}
			catch (void*)
			{
				Console::OutLn << Console::Colors::Error << "Please input a number!";
				kernel_size = 0;
			}
		}

		if (kernel_size > 0)
		{
			Console::Out << Console::Colors::Success << "Kernel Size " << "[" << kernel_size << "]\n";
			break;
		}
		else Console::Out << Console::Colors::Error << "Kernel Size must be greater than zero!\n" << "Please input Kernel Size: ";
	}

	// :: Output File ::
	string out_filename;
	bool out_filename_created = false;
	while (!out_filename_created)
	{
		Console::Out << "Output Filename: ";
		std::cin >> out_filename;
		if (filename == "q") exit(0);
		else file_exists = FileHelper::FileExists(out_filename);

		if (file_exists)
		{
			Console::Out << Console::Colors::Text << "File Exists! Overwrite [Y/N]" << "[" << filename << "]\n";
			string answer;
			std::cin >> answer;
			out_filename_created = (answer == "Y" || answer == "y");
		}
		else out_filename_created = true;
	}
	Console::Out << Console::Colors::Success << "File Output Name:" << "[" << out_filename << "]\n";

	unsigned long long start_time = GetTickCount64();

	picopng::PNG png(filename);
	float searchDistance = (float)kernel_size;

	if (png.Width > 0 && png.Height > 0 && png.Data.size() > 0) // Ensure PNG file is ok
	{
		size_t png_data_size = png.Data.size();

		// Create an array to store the pixel distance data
		std::vector<float> distance_data;
		distance_data.resize(png_data_size / 4);

		// Log the initial progress.
		string str_out = string("Completed: ") + std::to_string(0) + "/" + std::to_string(png.Width) + "\n";
		Console::Out << str_out;

		// Record start time
		unsigned long long last_time = GetTickCount64();

		// Loop Variables
		float delta = 0;
		unsigned char data = 0;
		float init = (float)sqrt((double)(png.Width*png.Width + png.Height*png.Height)); // Maximum possible distance
		float max = 0.0f;
		const float min = 0.0f;

		for (unsigned int i = 0; i < png.Width; i++) //0
		{
			for (unsigned int j = 0; j < png.Height; j++) //1
			{
				float *output = &distance_data[i + j * png.Width];
				*output = init;
				data = png.Data[4 * (i + j * png.Width)]; // Get the Data

				if (data <= 0) // Ensure the pixel isn't going to be of distance 0
				{
					for (unsigned int k = 0; k < png.Width; k++) //2
					{
						for (unsigned int w = 0; w < png.Height; w++) //3
						{
							data = png.Data[4 * (k + w * png.Width)]; // Get the Data
							if (data > 0)
							{
								// Calculate distance and maintain maximum precision
								// Calculate the distance squared
								// NOTE: Leave as distance squared and use square root later to improve performance.
								long long x_dist = (long long)i - k;
								long long y_dist = (long long)j - w;
								float distance = (float)(x_dist*x_dist + y_dist*y_dist);

								if (distance < *output) *output = distance;
								if (distance > max) max = distance;
								//if (distance < min) min = distance;

								if (*output <= 1) break;;
							}
						}
						if (*output <= 1) break;;
					}
				}
				else *output = 0;
			}

			// :: Calculate the remaning time and log progress to console ::
			{
				unsigned long long current_time = GetTickCount64();
				unsigned long long delta_time = current_time - last_time;
				last_time = current_time;
				float f_delta_time = (float)((double)delta_time / 1000);
				float more_ticks = (float)(png.Width - i);
				if (i == 0) delta = f_delta_time;
				delta = (delta * 2 + f_delta_time) / 3.0f;
				float remaning_time = delta * more_ticks;

				str_out = string("Completed: ") + std::to_string(i + 1) + "/" + std::to_string(png.Width) + " Remaning: " + std::to_string(remaning_time) + "s\n";
				Console::Out << str_out;
			}
		}

		FileHelper::FreeVector(png.Data); // Free the PNG Source Data. It will no longer be used.

		// : Convert data into 0-1 byte data :
		std::vector<unsigned char> texture_data;
		texture_data.resize(png_data_size / 4);

		for (unsigned int i = 0; i < png.Width; i++) for (unsigned int j = 0; j < png.Height; j++)
		{
			float value = sqrtf(distance_data[i + j*png.Width]);

			// Clamp distance to -/+
			value = Math::Clamp(value, -searchDistance, +searchDistance);

			// Convert from -search,+search to 0,+search*2 and then convert to 0.0, 1.0 and invert
			value = 1.0f - Math::Clamp((value + searchDistance) / (searchDistance + searchDistance), 0, 1);

			texture_data[i + (png.Height - j - 1)*png.Width] = (unsigned char)(value*255.0f);
		}

		FileHelper::FreeVector(distance_data); // Free the Distance Data. It will no longer be used.

		// : Create Minochrome Bitmap Pixel Data
		std::vector<Pixel> bmp_data;
		bmp_data.resize(texture_data.size());
		for (unsigned int i = 0; i < png.Width; i++) for (unsigned int j = 0; j < png.Height; j++)
		{
			unsigned char data = texture_data[i + j*png.Width];
			bmp_data[i + j*png.Width].r = data;
			bmp_data[i + j*png.Width].g = data;
			bmp_data[i + j*png.Width].b = data;
		}

		FileHelper::FreeVector(texture_data); // Free the Texture Data. It will no longer be used.

		// Try and save the Bitmap and log the result.
		if (SaveBMP((unsigned char*)(&bmp_data[0]), bmp_data.size() * 3, png.Width, png.Height, (char*)out_filename.c_str()))
		{
			// Process completed sucessfully. Calculate time and display to console.
			unsigned long long time = GetTickCount64() - start_time;
			float ftime = (float)((double)time / 1000);
			Console::Out << Console::Colors::Success << "Process Complete: t["<< ftime <<"]" << "Saved to " << "[" << out_filename << "]\n";
		}
		// Something went wrong while trying to save the Bitmap File. Display an error message.
		else Console::Out << Console::Colors::Error << "Process Failed: " << "Could not save output bitmap file!\n";

		FileHelper::FreeVector(bmp_data); // Free the bitmap data so the application can idle with minimum memory usage.

	}
	// Something went wrong while trying to load the PNG File. Display an error message.
	else Console::Out << Console::Colors::Error << "Process Failed: " << "Bad PNG import!\n";

	system("pause"); // Wait for the user to exit the application.
}

bool Application::SaveBMP(unsigned char* data, DWORD data_size, int width, int height, char* filepath)
{
	BITMAPFILEHEADER bmfh;
	BITMAPINFOHEADER info;
	memset(&bmfh, 0, sizeof (BITMAPFILEHEADER));
	memset(&info, 0, sizeof (BITMAPINFOHEADER));

	bmfh.bfType = 0x4d42;       // 0x4d42 = 'BM'
	bmfh.bfReserved1 = 0;
	bmfh.bfReserved2 = 0;
	bmfh.bfSize = sizeof(BITMAPFILEHEADER)+
		sizeof(BITMAPINFOHEADER)+data_size;
	bmfh.bfOffBits = 0x36;

	info.biSize = sizeof(BITMAPINFOHEADER);
	info.biWidth = width;
	info.biHeight = height;
	info.biPlanes = 1;
	info.biBitCount = 24;
	info.biCompression = BI_RGB;
	info.biSizeImage = 0;
	info.biXPelsPerMeter = 0x0ec4;
	info.biYPelsPerMeter = 0x0ec4;
	info.biClrUsed = 0;
	info.biClrImportant = 0;

	HANDLE file = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_READ,
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (NULL == file)
	{
		CloseHandle(file);
		return false;
	}

	unsigned long bwritten;
	if (WriteFile(file, &bmfh, sizeof (BITMAPFILEHEADER),
		&bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	if (WriteFile(file, &info, sizeof (BITMAPINFOHEADER),
		&bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	if (WriteFile(file, data, data_size, &bwritten, NULL) == false)
	{
		CloseHandle(file);
		return false;
	}

	CloseHandle(file);
	return true;
}<|endoftext|>


<commit_before><commit_msg>remove a useless line<commit_after><|endoftext|>


<commit_before><commit_msg>Rename task configurables<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestWin32OpenGLRenderWindow.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTestUtilities.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkActor.h"
#include "vtkConeSource.h"
#include "vtkWin32OpenGLRenderWindow.h"
#include <vtkSmartPointer.h>
#include <vtkConeSource.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>

//This tests if the offscreen rendering works
static bool TestWin32OpenGLRenderWindowOffScreen(vtkWin32OpenGLRenderWindow* renderWindow)
{
  //Create a cone
  vtkSmartPointer<vtkConeSource> coneSource =
    vtkSmartPointer<vtkConeSource>::New();
  coneSource->Update();

  //Create a mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> mapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputConnection(coneSource->GetOutputPort());

  vtkSmartPointer<vtkActor> actor =
    vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);

  //Create a renderer, render window, and interactor
  vtkSmartPointer<vtkRenderer> renderer =
    vtkSmartPointer<vtkRenderer>::New();

  renderWindow->AddRenderer(renderer);

  //Add the actors to the scene
  renderer->AddActor(actor);
  renderer->SetBackground(.3, .2, .1); // Background color dark red

  //Render and interact
  renderWindow->SetOffScreenRendering(1);
  renderWindow->SetSize(100,100);
  renderWindow->Render();
  return 1;
}
int TestWin32OpenGLRenderWindow(int argc, char* argv[])
{
  vtkWin32OpenGLRenderWindow* renderWindow(NULL);

  vtkSmartPointer<vtkRenderWindow> renderWindowBase = vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow = vtkWin32OpenGLRenderWindow::SafeDownCast(renderWindowBase);

  TestWin32OpenGLRenderWindowOffScreen(renderWindow);

  return EXIT_SUCCESS;
}
<commit_msg>use vtkNew to make code cleaner<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestWin32OpenGLRenderWindow.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTestUtilities.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkActor.h"
#include "vtkConeSource.h"
#include "vtkWin32OpenGLRenderWindow.h"
#include <vtkConeSource.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkNew.h>

//This tests if the offscreen rendering works
static bool TestWin32OpenGLRenderWindowOffScreen(vtkWin32OpenGLRenderWindow* renderWindow)
{
  //Create a cone
  vtkNew<vtkConeSource> coneSource;
  coneSource->Update();

  //Create a mapper and actor
  vtkNew<vtkPolyDataMapper> mapper;
  mapper->SetInputConnection(coneSource->GetOutputPort());

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper.GetPointer());

  //Create a renderer, render window, and interactor
  vtkNew<vtkRenderer> renderer;
  renderWindow->AddRenderer(renderer.GetPointer());

  //Add the actors to the scene
  renderer->AddActor(actor.GetPointer());
  renderer->SetBackground(.3, .2, .1); // Background color dark red

  //Render and interact
  renderWindow->SetOffScreenRendering(1);
  renderWindow->SetSize(100,100);
  renderWindow->Render();
  return 1;
}
int TestWin32OpenGLRenderWindow(int argc, char* argv[])
{
  vtkWin32OpenGLRenderWindow* renderWindow(NULL);

  vtkNew<vtkRenderWindow> renderWindowBase;
  renderWindow = vtkWin32OpenGLRenderWindow::SafeDownCast(renderWindowBase.GetPointer());

  TestWin32OpenGLRenderWindowOffScreen(renderWindow);

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_IO_FileAccessException_inl_
#define _Stroika_Foundation_IO_FileAccessException_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Debug/Trace.h"
#include    "../Execution/Exceptions.h"

namespace   Stroika {
    namespace   Foundation  {
        namespace   IO {

            /*
             ********************************************************************************
             ***************************** IO::FileAccessException **************************
             ********************************************************************************
             */
            inline  String         FileAccessException::GetFileName () const
            {
                return fFileName_;
            }
            inline  FileAccessMode  FileAccessException::GetFileAccessMode () const
            {
                return fFileAccessMode_;
            }

        }
        namespace   Execution {

            template    <>
            [[noreturn]]    inline  void    Throw (const IO::FileAccessException& e2Throw)
            {
#if     qStroika_Foundation_Exection_Exceptions_TraceThrowpointBacktrace
                DbgTrace (L"Throwing FileAccessException: fFileName='%s'; FileAccessMode=%s from %s", e2Throw.GetFileName ().c_str (), Configuration::DefaultNames<IO::FileAccessMode>::k.GetName (e2Throw.GetFileAccessMode ()), Private_::GetBT_s ().c_str ());
#else
                DbgTrace (L"Throwing FileAccessException: fFileName='%s'; FileAccessMode=%s", e2Throw.GetFileName ().c_str (), Configuration::DefaultNames<IO::FileAccessMode>::k.GetName (e2Throw.GetFileAccessMode ()));
#endif
                throw e2Throw;
            }

        }

    }
}
#endif  /*_Stroika_Foundation_IO_FileAccessException_inl_*/
<commit_msg>typo in recent fix for Foundation/IO/FileAccessException DoThrow<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Foundation_IO_FileAccessException_inl_
#define _Stroika_Foundation_IO_FileAccessException_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Debug/Trace.h"
#include    "../Execution/Exceptions.h"

namespace   Stroika {
    namespace   Foundation  {
        namespace   IO {

            /*
             ********************************************************************************
             ***************************** IO::FileAccessException **************************
             ********************************************************************************
             */
            inline  String         FileAccessException::GetFileName () const
            {
                return fFileName_;
            }
            inline  FileAccessMode  FileAccessException::GetFileAccessMode () const
            {
                return fFileAccessMode_;
            }

        }
        namespace   Execution {

            template    <>
            [[noreturn]]    inline  void    Throw (const IO::FileAccessException& e2Throw)
            {
#if     qStroika_Foundation_Exection_Exceptions_TraceThrowpointBacktrace
                DbgTrace (L"Throwing FileAccessException: fFileName='%s'; FileAccessMode=%s from %s", e2Throw.GetFileName ().c_str (), Configuration::DefaultNames<IO::FileAccessMode>::k.GetName (e2Throw.GetFileAccessMode ()), Private_::GetBT_ws ().c_str ());
#else
                DbgTrace (L"Throwing FileAccessException: fFileName='%s'; FileAccessMode=%s", e2Throw.GetFileName ().c_str (), Configuration::DefaultNames<IO::FileAccessMode>::k.GetName (e2Throw.GetFileAccessMode ()));
#endif
                throw e2Throw;
            }

        }

    }
}
#endif  /*_Stroika_Foundation_IO_FileAccessException_inl_*/
<|endoftext|>


<commit_before>#include <QtTest/QtTest>

#include "tarsnaptask.h"

class TestTask : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void sleep_ok();
    void sleep_fail();
    void sleep_crash();
    void sleep_filenotfound();

private:
    QString get_script(QString scriptname);
};

void TestTask::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);
}

QString TestTask::get_script(QString scriptname)
{
    QDir dir = QDir(QCoreApplication::applicationDirPath());

#ifdef Q_OS_OSX
    // Handle the OSX app bundle.
    dir.cdUp();
    dir.cdUp();
    dir.cdUp();
#endif

    return dir.absolutePath() + "/" + scriptname;
}

#define RUN_SCRIPT(scriptname)                                                 \
    TarsnapTask *task = new TarsnapTask();                                     \
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));                 \
    QSignalSpy   sig_fin(task,                                                 \
                       SIGNAL(finished(QVariant, int, QString, QString)));     \
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));                           \
                                                                               \
    task->setCommand("/bin/sh");                                               \
    task->setArguments(QStringList(get_script(scriptname)));                   \
    task->run();                                                               \
    QVERIFY(sig_started.count() == 1);                                         \
    QVERIFY(sig_dequeue.count() == 1);                                         \
    delete task;

void TestTask::sleep_ok()
{
    RUN_SCRIPT("sleep-1-exit-0.sh");
    // We got a "finished" signal, with exit code 0.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 0);
}

void TestTask::sleep_fail()
{
    RUN_SCRIPT("sleep-1-exit-1.sh");
    // We got a "finished" signal, with exit code 1.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 1);
}

void TestTask::sleep_crash()
{
    RUN_SCRIPT("sleep-1-crash.sh");
    // Despite the crash, we should still get a "finished" signal.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_CRASHED);
}

void TestTask::sleep_filenotfound()
{
    // This script should not exist.
    RUN_SCRIPT("sleep-1-filenotfound.sh");
    // We got a "finished" signal, with sh exit code 127 ("command not found").
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 127);
}

QTEST_MAIN(TestTask)
#include "main.moc"
<commit_msg>tests/task: handle fail cmd: "command not found"<commit_after>#include <QtTest/QtTest>

#include "tarsnaptask.h"

class TestTask : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void sleep_ok();
    void sleep_fail();
    void sleep_crash();
    void sleep_filenotfound();
    void cmd_filenotfound();

private:
    QString get_script(QString scriptname);
};

void TestTask::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);
}

QString TestTask::get_script(QString scriptname)
{
    QDir dir = QDir(QCoreApplication::applicationDirPath());

#ifdef Q_OS_OSX
    // Handle the OSX app bundle.
    dir.cdUp();
    dir.cdUp();
    dir.cdUp();
#endif

    return dir.absolutePath() + "/" + scriptname;
}

#define RUN_SCRIPT(scriptname)                                                 \
    TarsnapTask *task = new TarsnapTask();                                     \
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));                 \
    QSignalSpy   sig_fin(task,                                                 \
                       SIGNAL(finished(QVariant, int, QString, QString)));     \
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));                           \
                                                                               \
    task->setCommand("/bin/sh");                                               \
    task->setArguments(QStringList(get_script(scriptname)));                   \
    task->run();                                                               \
    QVERIFY(sig_started.count() == 1);                                         \
    QVERIFY(sig_dequeue.count() == 1);                                         \
    delete task;

void TestTask::sleep_ok()
{
    RUN_SCRIPT("sleep-1-exit-0.sh");
    // We got a "finished" signal, with exit code 0.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 0);
}

void TestTask::sleep_fail()
{
    RUN_SCRIPT("sleep-1-exit-1.sh");
    // We got a "finished" signal, with exit code 1.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 1);
}

void TestTask::sleep_crash()
{
    RUN_SCRIPT("sleep-1-crash.sh");
    // Despite the crash, we should still get a "finished" signal.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_CRASHED);
}

void TestTask::sleep_filenotfound()
{
    // This script should not exist.
    RUN_SCRIPT("sleep-1-filenotfound.sh");
    // We got a "finished" signal, with sh exit code 127 ("command not found").
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 127);
}

void TestTask::cmd_filenotfound()
{
    TarsnapTask *task = new TarsnapTask();
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));
    QSignalSpy sig_fin(task, SIGNAL(finished(QVariant, int, QString, QString)));
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));

    task->setCommand("/fake/dir/fake-cmd");
    task->run();
    // We got a "finished" signal, with exit code EXIT_DID_NOT_START.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_DID_NOT_START);
}

QTEST_MAIN(TestTask)
#include "main.moc"
<|endoftext|>


<commit_before>///
/// \file PWGCF/FEMTOSCOPY/macros/Train/PionPionFemto/AddTaskPionPion.C
/// \author Andrew Kubera, Ohio State University, andrew.kubera@cern.ch
///

#ifndef __CINT__

#include <TString.h>
#include <TList.h>
#include <TObjArray.h>

#endif

///
/// \brief Adds an AliAnalysisTaskFemto analysis object, constructed
///        with parameters provided, to the global AliAnalysisManager.
///
/// This macro creates and returns an AliAnalysisTaskFemto object.
/// The task object is given a macro
/// is given the config macro "Train/PionPionFemto/ConfigFemtoAnalysis.C"
/// which is run to create the analysis objects.
/// This is fixed (for now), and if an alternative is required, you
/// should use the general AddTaskFemto.C macro.
///
/// Subwagons are supported, the name of which will be appended to
/// the task name.
/// The task name by default is "TaskPionPionFemto" which cannot be
/// changed.
///
/// The output container name is fixed at the standard "femtolist".
///
/// \param configuration
///     A string containing commands to execute, separated by semicolons.
///     Assign the old parameters using this command.
///     Single quotes are turned to double quotes.
///
///     * macro: Path to the FemtoConfig macro to load; "%%" is
///          expaneded to directory containing this file.
///     * output_filename: Name of the output file to produce.
///         Default generated by AliAnalysisManager::GetCommonFileName()
///     * output_container: Name of top-level ROOT directory in the output file.
///         Default is the classic 'PWG2FEMTO'.
///     * container: Name of the AliAnalysis container.
///     * task_name: Name of the AliAnalysisTask - May need to be unique...
///     * verbose: Task created in verbose mode
///
/// \param params
///     A string forwarded to the ConfigFemtoAnalysis macro for parsing.
///     This string is wrapped in double-quotes so escaping some to
///     ensure results is a string is unneccessary.
///
/// \param subwagon_suffix
///     If this macro is run in a train with subwagons, this will be
///     set with the identifier.
///
AliAnalysisTaskFemto* AddTaskPionPion(TString configuration,
                                      TString params,
                                      TString subwagon_suffix="")
{ // Adds a Pion-Pion Femtoscopy task to the manager

  const TString AUTO_DIRECTORY = "$ALICE_PHYSICS/PWGCF/FEMTOSCOPY/macros/Train/PionPionFemto",
                DEFAULT_MACRO = "%%/ConfigFemtoAnalysis.C",
                DEFAULT_CONTAINER_NAME = "pionpion_femtolist",
                DEFAULT_OUTPUT_CONTAINER = "PWG2FEMTO",
                DEFAULT_TASK_NAME = "TaskPionPion",
                DEFAULT_SUBWAGON_TYPE = "centrality";

  // Get the global manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskPionPion", "Could not get the global AliAnalysisManager.");
    return NULL;
  }

  TString macro = DEFAULT_MACRO,
          output_filename = mgr->GetCommonFileName(),
          task_name = DEFAULT_TASK_NAME,
          container = DEFAULT_CONTAINER_NAME,
          output_container = DEFAULT_OUTPUT_CONTAINER,
          subwagon_type = DEFAULT_SUBWAGON_TYPE;

  bool verbose = kFALSE;

  TObjArray* lines = configuration.Tokenize("\n;");

  TIter next_line(lines);
  TObject *line_obj = NULL;

  while (line_obj = next_line()) {
    TString cmd = ((TObjString*)line_obj)->String().Strip(TString::kBoth, ' ');
    cmd.ReplaceAll("'", '"');
    std::cout << "running `" << cmd  << "`\n";
    gROOT->ProcessLineFast(cmd + ';');
  }

  // Replace %% with this directory for convenience
  macro.ReplaceAll("%%", AUTO_DIRECTORY);

  // Dealing with subwagons
  if (subwagon_suffix) {
    subwagon_type.ToLower();

    if (subwagon_type == "centrality") {
      params = TString::Format("~use_subwagon_centrality=true; ~subwagon_centrality='%s';", subwagon_suffix.Data()) + params.Data();
    } else {
      std::cerr << "AddTaskPionPion - Unexpected subwagon_type '" << subwagon_type << "' - Ignoring\n";
    }
  }

  cout << "[AddTaskPionPion]\n"
          "   output: '" << output_filename << "'\n"
          "   macro: '" << macro << "'\n"
          "   params: '" << params << "'\n";

  // The analysis config macro for PionPionFemto accepts a single string
  // argument, which it interprets.
  // This line escapes some escapable characters (backslash, newline, tab)
  // and wraps that string in double quotes, ensuring that the interpreter
  // reads a string when passing to the macro.
  const TString analysis_params = '"' + params.ReplaceAll("\\", "\\\\")
                                              .ReplaceAll("\n", "\\n")
                                              .ReplaceAll("\"", "\\\"")
                                              .ReplaceAll("\t", "\\t") + '"';

  AliAnalysisTaskFemto *taskfemto = new AliAnalysisTaskFemto(
    task_name,
    macro,
    analysis_params,
    verbose
  );

  mgr->AddTask(taskfemto);

  const TString outputfile = (output_container == "")
                           ? output_filename
                           : TString::Format("%s:%s", output_filename.Data(), output_container.Data());

  AliAnalysisDataContainer *out_container = mgr->CreateContainer(container,
                                                                 TList::Class(),
                                                                 AliAnalysisManager::kOutputContainer,
                                                                 outputfile);

  // connect task to the containers
  mgr->ConnectInput(taskfemto, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskfemto, 0, out_container);

  // Return the task pointer
  return taskfemto;
}
<commit_msg>PWGCF: PionPionAnalysis - Correct check for string "emptiness"<commit_after>///
/// \file PWGCF/FEMTOSCOPY/macros/Train/PionPionFemto/AddTaskPionPion.C
/// \author Andrew Kubera, Ohio State University, andrew.kubera@cern.ch
///

#ifndef __CINT__

#include <TString.h>
#include <TList.h>
#include <TObjArray.h>

#endif

///
/// \brief Adds an AliAnalysisTaskFemto analysis object, constructed
///        with parameters provided, to the global AliAnalysisManager.
///
/// This macro creates and returns an AliAnalysisTaskFemto object.
/// The task object is given a macro
/// is given the config macro "Train/PionPionFemto/ConfigFemtoAnalysis.C"
/// which is run to create the analysis objects.
/// This is fixed (for now), and if an alternative is required, you
/// should use the general AddTaskFemto.C macro.
///
/// Subwagons are supported, the name of which will be appended to
/// the task name.
/// The task name by default is "TaskPionPionFemto" which cannot be
/// changed.
///
/// The output container name is fixed at the standard "femtolist".
///
/// \param configuration
///     A string containing commands to execute, separated by semicolons.
///     Assign the old parameters using this command.
///     Single quotes are turned to double quotes.
///
///     * macro: Path to the FemtoConfig macro to load; "%%" is
///          expaneded to directory containing this file.
///     * output_filename: Name of the output file to produce.
///         Default generated by AliAnalysisManager::GetCommonFileName()
///     * output_container: Name of top-level ROOT directory in the output file.
///         Default is the classic 'PWG2FEMTO'.
///     * container: Name of the AliAnalysis container.
///     * task_name: Name of the AliAnalysisTask - May need to be unique...
///     * verbose: Task created in verbose mode
///
/// \param params
///     A string forwarded to the ConfigFemtoAnalysis macro for parsing.
///     This string is wrapped in double-quotes so escaping some to
///     ensure results is a string is unneccessary.
///
/// \param subwagon_suffix
///     If this macro is run in a train with subwagons, this will be
///     set with the identifier.
///
AliAnalysisTaskFemto* AddTaskPionPion(TString configuration,
                                      TString params,
                                      TString subwagon_suffix="")
{ // Adds a Pion-Pion Femtoscopy task to the manager

  const TString AUTO_DIRECTORY = "$ALICE_PHYSICS/PWGCF/FEMTOSCOPY/macros/Train/PionPionFemto",
                DEFAULT_MACRO = "%%/ConfigFemtoAnalysis.C",
                DEFAULT_CONTAINER_NAME = "pionpion_femtolist",
                DEFAULT_OUTPUT_CONTAINER = "PWG2FEMTO",
                DEFAULT_TASK_NAME = "TaskPionPion",
                DEFAULT_SUBWAGON_TYPE = "centrality";

  // Get the global manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskPionPion", "Could not get the global AliAnalysisManager.");
    return NULL;
  }

  TString macro = DEFAULT_MACRO,
          output_filename = mgr->GetCommonFileName(),
          task_name = DEFAULT_TASK_NAME,
          container = DEFAULT_CONTAINER_NAME,
          output_container = DEFAULT_OUTPUT_CONTAINER,
          subwagon_type = DEFAULT_SUBWAGON_TYPE;

  bool verbose = kFALSE;

  TObjArray* lines = configuration.Tokenize("\n;");

  TIter next_line(lines);
  TObject *line_obj = NULL;

  while (line_obj = next_line()) {
    TString cmd = ((TObjString*)line_obj)->String().Strip(TString::kBoth, ' ');
    cmd.ReplaceAll("'", '"');
    std::cout << "running `" << cmd  << "`\n";
    gROOT->ProcessLineFast(cmd + ';');
  }

  // Replace %% with this directory for convenience
  macro.ReplaceAll("%%", AUTO_DIRECTORY);

  // Dealing with subwagons
  if (!subwagon_suffix.IsWhitespace()) {
    subwagon_type.ToLower();

    if (subwagon_type == "centrality") {
      params = TString::Format("~use_subwagon_centrality=true; ~subwagon_centrality='%s';", subwagon_suffix.Data()) + params.Data();
    } else {
      std::cerr << "AddTaskPionPion - Unexpected subwagon_type '" << subwagon_type << "' - Ignoring\n";
    }
  }

  cout << "[AddTaskPionPion]\n"
          "   output: '" << output_filename << "'\n"
          "   macro: '" << macro << "'\n"
          "   params: '" << params << "'\n";

  // The analysis config macro for PionPionFemto accepts a single string
  // argument, which it interprets.
  // This line escapes some escapable characters (backslash, newline, tab)
  // and wraps that string in double quotes, ensuring that the interpreter
  // reads a string when passing to the macro.
  const TString analysis_params = '"' + params.ReplaceAll("\\", "\\\\")
                                              .ReplaceAll("\n", "\\n")
                                              .ReplaceAll("\"", "\\\"")
                                              .ReplaceAll("\t", "\\t") + '"';

  AliAnalysisTaskFemto *taskfemto = new AliAnalysisTaskFemto(
    task_name,
    macro,
    analysis_params,
    verbose
  );

  mgr->AddTask(taskfemto);

  const TString outputfile = (output_container == "")
                           ? output_filename
                           : TString::Format("%s:%s", output_filename.Data(), output_container.Data());

  AliAnalysisDataContainer *out_container = mgr->CreateContainer(container,
                                                                 TList::Class(),
                                                                 AliAnalysisManager::kOutputContainer,
                                                                 outputfile);

  // connect task to the containers
  mgr->ConnectInput(taskfemto, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(taskfemto, 0, out_container);

  // Return the task pointer
  return taskfemto;
}
<|endoftext|>


<commit_before><commit_msg>add back<commit_after><|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_TRY_HPP__
#define __STOUT_TRY_HPP__

#include <assert.h>

#include <iostream>
#include <string>

#include <stout/abort.hpp>
#include <stout/error.hpp>
#include <stout/option.hpp>
#include <stout/some.hpp>

// This class can represent only one of these states at a time:
//   1) A value of T.
//   2) An error state, with a corresponding error string.
// Calling 'isSome' will return true if it stores a value, in which
// case calling 'get' will return a constant reference to the T
// stored. Calling 'isError' will return true if it stores an error,
// in which case calling 'error' will return the error string.
template <typename T, typename E = Error>
class Try
{
public:
  static_assert(
      std::is_base_of<Error, E>::value,
      "An error type must be, or be inherited from 'Error'.");

  static Try some(const T& t) { return Try(t); }
  static Try error(const E& e) { return Try(e); }

  Try(const T& t)
    : data(Some(t)) {}

  template <
      typename U,
      typename = typename std::enable_if<
          std::is_constructible<T, const U&>::value>::type>
  Try(const U& u) : data(Some(u)) {}

  Try(const E& error) : error_(error) {}

  Try(T&& t)
    : data(Some(std::move(t))) {}

  // We don't need to implement these because we are leveraging
  // Option<T>.
  Try(const Try& that) = default;
  Try(Try&& that) = default;

  ~Try() = default;

  Try& operator=(const Try& that) = default;
  Try& operator=(Try&& that) = default;

  // 'isSome' and 'isError' are mutually exclusive. They correspond
  // to the underlying state of the Option.
  bool isSome() const { return data.isSome(); }
  bool isError() const { return data.isNone(); }

  T& get() & { return get(*this); }
  const T& get() const & { return get(*this); }
  T&& get() && { return get(std::move(*this)); }
  const T&& get() const && { return get(std::move(*this)); }

  const T* operator->() const { return &get(); }
  T* operator->() { return &get(); }

  // NOTE: This function is intended to return the error of type `E`.
  // However, we return a `std::string` if `E` == `Error` since that's what it
  // used to return, and it's the only data that `Error` holds anyway.
  const typename std::conditional<
      std::is_same<E, Error>::value, std::string, E>::type& error() const
  {
    assert(data.isNone());
    assert(error_.isSome());
    return error_impl(error_.get());
  }

private:
  static const std::string& error_impl(const Error& err) { return err.message; }

  template <typename Self>
  static auto get(Self&& self) -> decltype(std::forward<Self>(self).data.get())
  {
    if (!self.data.isSome()) {
      assert(self.error_.isSome());
      ABORT("Try::get() but state == ERROR: " + self.error_->message);
    }
    return std::forward<Self>(self).data.get();
  }

  template <typename Err>
  static const Err& error_impl(const Err& err) { return err; }

  // We leverage Option<T> to avoid dynamic allocation of T. This
  // means that the storage for T will be included in this object
  // (Try<T>). Since Option<T> keeps track of whether a value is
  // stored, we just ask it when we want to know whether we are
  // storing a value or an error. Another advantage of leveraging
  // Option<T> is that it takes care of all the manual construction
  // and destruction. This makes the code for Try<T> really simple!
  Option<T> data;
  Option<E> error_;
};

#endif // __STOUT_TRY_HPP__
<commit_msg>Added `Try` constructors from `_Some`.<commit_after>// 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.

#ifndef __STOUT_TRY_HPP__
#define __STOUT_TRY_HPP__

#include <assert.h>

#include <iostream>
#include <string>

#include <stout/abort.hpp>
#include <stout/error.hpp>
#include <stout/option.hpp>
#include <stout/some.hpp>

// This class can represent only one of these states at a time:
//   1) A value of T.
//   2) An error state, with a corresponding error string.
// Calling 'isSome' will return true if it stores a value, in which
// case calling 'get' will return a constant reference to the T
// stored. Calling 'isError' will return true if it stores an error,
// in which case calling 'error' will return the error string.
template <typename T, typename E = Error>
class Try
{
public:
  static_assert(
      std::is_base_of<Error, E>::value,
      "An error type must be, or be inherited from 'Error'.");

  static Try some(const T& t) { return Try(t); }
  static Try error(const E& e) { return Try(e); }

  Try(const T& t)
    : data(Some(t)) {}

  template <
      typename U,
      typename = typename std::enable_if<
          std::is_constructible<T, const U&>::value>::type>
  Try(const U& u) : data(Some(u)) {}

  Try(const E& error) : error_(error) {}

  Try(T&& t)
    : data(Some(std::move(t))) {}

  template <typename U>
  Try(const _Some<U>& some) : data(some) {}

  template <typename U>
  Try(_Some<U>&& some) : data(std::move(some)) {}

  // We don't need to implement these because we are leveraging
  // Option<T>.
  Try(const Try& that) = default;
  Try(Try&& that) = default;

  ~Try() = default;

  Try& operator=(const Try& that) = default;
  Try& operator=(Try&& that) = default;

  // 'isSome' and 'isError' are mutually exclusive. They correspond
  // to the underlying state of the Option.
  bool isSome() const { return data.isSome(); }
  bool isError() const { return data.isNone(); }

  T& get() & { return get(*this); }
  const T& get() const & { return get(*this); }
  T&& get() && { return get(std::move(*this)); }
  const T&& get() const && { return get(std::move(*this)); }

  const T* operator->() const { return &get(); }
  T* operator->() { return &get(); }

  // NOTE: This function is intended to return the error of type `E`.
  // However, we return a `std::string` if `E` == `Error` since that's what it
  // used to return, and it's the only data that `Error` holds anyway.
  const typename std::conditional<
      std::is_same<E, Error>::value, std::string, E>::type& error() const
  {
    assert(data.isNone());
    assert(error_.isSome());
    return error_impl(error_.get());
  }

private:
  static const std::string& error_impl(const Error& err) { return err.message; }

  template <typename Self>
  static auto get(Self&& self) -> decltype(std::forward<Self>(self).data.get())
  {
    if (!self.data.isSome()) {
      assert(self.error_.isSome());
      ABORT("Try::get() but state == ERROR: " + self.error_->message);
    }
    return std::forward<Self>(self).data.get();
  }

  template <typename Err>
  static const Err& error_impl(const Err& err) { return err; }

  // We leverage Option<T> to avoid dynamic allocation of T. This
  // means that the storage for T will be included in this object
  // (Try<T>). Since Option<T> keeps track of whether a value is
  // stored, we just ask it when we want to know whether we are
  // storing a value or an error. Another advantage of leveraging
  // Option<T> is that it takes care of all the manual construction
  // and destruction. This makes the code for Try<T> really simple!
  Option<T> data;
  Option<E> error_;
};

#endif // __STOUT_TRY_HPP__
<|endoftext|>


<commit_before>#include <fbx.h>
#include <opengl.h>
using namespace linalg::aliases;

#include <iostream>
#include <fstream>
#include <chrono>

int main() try
{
    std::ifstream in("assets/helmet-mesh.fbx", std::ifstream::binary);
    const auto doc = fbx::load(in);
    std::cout << "FBX Version " << doc.version << std::endl;
    for(auto & node : doc.nodes) std::cout << node << std::endl;

    auto models = load_models(doc);

    // Compute tangent space basis
    for(auto & m : models)
    {
        for(auto & g : m.geoms)
        {
            for(auto t : g.triangles)
            {
                auto & v0 = g.vertices[t.x], & v1 = g.vertices[t.y], & v2 = g.vertices[t.z];
                const float3 e1 = v1.position - v0.position, e2 = v2.position - v0.position;
                const float2 d1 = v1.texcoord - v0.texcoord, d2 = v2.texcoord - v0.texcoord;
                const float3 dpds = float3(d2.y * e1.x - d1.y * e2.x, d2.y * e1.y - d1.y * e2.y, d2.y * e1.z - d1.y * e2.z) / cross(d1, d2);
                const float3 dpdt = float3(d1.x * e2.x - d2.x * e1.x, d1.x * e2.y - d2.x * e1.y, d1.x * e2.z - d2.x * e1.z) / cross(d1, d2);
                v0.tangent += dpds; v1.tangent += dpds; v2.tangent += dpds;
                v0.bitangent += dpdt; v1.bitangent += dpdt; v2.bitangent += dpdt;
            }
            for(auto & v : g.vertices)
            {
                v.tangent = normalize(v.tangent);
                v.bitangent = normalize(v.bitangent);
            }
        }
    }

    glfwInit();
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_SRGB_CAPABLE, 1);
    auto win = glfwCreateWindow(640, 480, "Example Game", nullptr, nullptr);
    glfwMakeContextCurrent(win);
    glfwSwapInterval(1);
    glewInit();

    GLuint cube_tex;
    glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &cube_tex);
    glTextureStorage2D(cube_tex, 12, GL_SRGB8, 2048, 2048);
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_X, "assets/posx.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, "assets/negx.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, "assets/posy.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, "assets/negy.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, "assets/posz.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, "assets/negz.jpg");
    glGenerateTextureMipmap(cube_tex);
    glTextureParameteri(cube_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTextureParameteri(cube_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTextureParameteri(cube_tex, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTextureParameteri(cube_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTextureParameteri(cube_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    auto program = link_program({
        compile_shader(GL_VERTEX_SHADER, R"(#version 450
            uniform mat4 u_model_matrix;
            uniform mat4 u_view_proj_matrix;
            layout(location = 0) in vec3 v_position;
            layout(location = 1) in vec3 v_normal;
            layout(location = 2) in vec2 v_texcoord;
            layout(location = 3) in vec3 v_tangent;
            layout(location = 4) in vec3 v_bitangent;
            out vec3 position;
            out vec3 normal;
            out vec2 texcoord;
            out vec3 tangent;
            out vec3 bitangent;
            void main()
            {
                position = (u_model_matrix * vec4(v_position, 1)).xyz;
                normal = normalize((u_model_matrix * vec4(v_normal, 0)).xyz);
                texcoord = v_texcoord;
                tangent = normalize((u_model_matrix * vec4(v_tangent, 0)).xyz);
                bitangent = normalize((u_model_matrix * vec4(v_bitangent, 0)).xyz);
                gl_Position = u_view_proj_matrix * vec4(position, 1);
            }
        )"),
        compile_shader(GL_FRAGMENT_SHADER, R"(#version 450
            uniform vec3 u_eye_position;
            uniform vec3 u_ambient_light;
            uniform vec3 u_light_direction;
            uniform vec3 u_light_color;
            layout(binding = 0) uniform sampler2D u_albedo;
            layout(binding = 1) uniform sampler2D u_normal;
            layout(binding = 2) uniform sampler2D u_metallic;
            layout(binding = 4) uniform samplerCube u_env;
            in vec3 position;
            in vec3 normal;
            in vec2 texcoord;
            in vec3 tangent;
            in vec3 bitangent;
            layout(location = 0) out vec4 f_color;
            void main()
            {
                vec3 eye_vec = normalize(u_eye_position - position);
                vec3 albedo = texture(u_albedo, texcoord).rgb;
                vec3 tan_normal = normalize(texture(u_normal, texcoord).xyz*2-1);
                vec3 normal_vec = normalize(normalize(tangent)*tan_normal.x + normalize(bitangent)*tan_normal.y + normalize(normal)*tan_normal.z);
                vec3 refl_vec = normal_vec*(dot(eye_vec, normal_vec)*2) - eye_vec;

                vec3 refl_light = albedo * texture(u_env, refl_vec).rgb*2;

                vec3 light = u_ambient_light;

                vec3 light_vec = u_light_direction;
                light += albedo * u_light_color * max(dot(normal_vec, light_vec), 0);
                vec3 half_vec = normalize(light_vec + eye_vec);
                light += u_light_color * pow(max(dot(normal_vec, half_vec), 0), 128);

                float metallic = texture(u_metallic, texcoord).r;

                f_color = vec4(light*(1-metallic) + refl_light*metallic, 1);
            }
        )")
    });

    auto tex_albedo = load_texture("assets/helmet-albedo.jpg", GL_SRGB8);
    auto tex_normal = load_texture("assets/helmet-normal.jpg", GL_RGB8);
    auto tex_metallic = load_texture("assets/helmet-metallic.jpg", GL_R8);

    float3 camera_position {0,0,20};
    float camera_yaw {0}, camera_pitch {0};
    double2 last_cursor;
    auto t0 = std::chrono::high_resolution_clock::now();
    while(!glfwWindowShouldClose(win))
    {
        glfwPollEvents();

        // Compute timestep
        const auto t1 = std::chrono::high_resolution_clock::now();
        const auto timestep = std::chrono::duration<float>(t1 - t0).count();
        t0 = t1;

        // Handle mouselook
        double2 cursor;
        glfwGetCursorPos(win, &cursor.x, &cursor.y);
        if(glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT))
        {
            const auto move = float2(cursor - last_cursor);
            camera_yaw -= move.x * 0.01f;
            camera_pitch = std::max(-1.5f, std::min(1.5f, camera_pitch - move.y * 0.01f));
        }
        last_cursor = cursor;

        // Handle WASD
        const float4 camera_orientation = qmul(rotation_quat(float3{0,1,0}, camera_yaw), rotation_quat(float3{1,0,0}, camera_pitch));
        if(glfwGetKey(win, GLFW_KEY_W)) camera_position -= qzdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_A)) camera_position -= qxdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_S)) camera_position += qzdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_D)) camera_position += qxdir(camera_orientation) * (timestep * 50);

        // Determine matrices
        int width, height;
        glfwGetFramebufferSize(win, &width, &height);
        const auto proj_matrix = linalg::perspective_matrix(1.0f, (float)width/height, 1.0f, 1000.0f);
        const auto view_matrix = inverse(pose_matrix(camera_orientation, camera_position));
        const auto view_proj_matrix = mul(proj_matrix, view_matrix);

        // Clear the viewport
        glEnable(GL_FRAMEBUFFER_SRGB);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glEnable(GL_DEPTH_TEST);
        glUseProgram(program);
        glUniformMatrix4fv(glGetUniformLocation(program, "u_view_proj_matrix"), 1, GL_FALSE, &view_proj_matrix.x.x);
        glUniform3fv(glGetUniformLocation(program, "u_eye_position"), 1, &camera_position.x);

        const float3  ambient_light {0.01f,0.01f,0.01f}, light_direction {normalize(float3{1,5,2})}, light_color {0.8f,0.7f,0.5f};
        glUniform3fv(glGetUniformLocation(program, "u_ambient_light"), 1, &ambient_light.x);
        glUniform3fv(glGetUniformLocation(program, "u_light_direction"), 1, &light_direction.x);
        glUniform3fv(glGetUniformLocation(program, "u_light_color"), 1, &light_color.x);

        for(auto & m : models)
        {
            const auto model_matrix = m.get_model_matrix();
            glUniformMatrix4fv(glGetUniformLocation(program, "u_model_matrix"), 1, GL_FALSE, &model_matrix.x.x);
            glBindTextureUnit(0, tex_albedo);
            glBindTextureUnit(1, tex_normal);
            glBindTextureUnit(2, tex_metallic);
            glBindTextureUnit(4, cube_tex);

            for(auto & g : m.geoms)
            {
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->position);
                glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->normal);
                glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->texcoord);
                glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->tangent);
                glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->bitangent);
                for(GLuint i : {0,1,2,3,4}) glEnableVertexAttribArray(i);
                glDrawElements(GL_TRIANGLES, g.triangles.size()*3, GL_UNSIGNED_INT, g.triangles.data());
            }
        }

        // Present
        glfwSwapBuffers(win);
    }

    glfwDestroyWindow(win);
    glfwTerminate();
    return EXIT_SUCCESS;
}
catch(const std::exception & e)
{
    std::cerr << "\n" << e.what() << std::endl;
    return EXIT_FAILURE;
}<commit_msg>Use seamless cubemap filtering.<commit_after>#include <fbx.h>
#include <opengl.h>
using namespace linalg::aliases;

#include <iostream>
#include <fstream>
#include <chrono>

int main() try
{
    std::ifstream in("assets/helmet-mesh.fbx", std::ifstream::binary);
    const auto doc = fbx::load(in);
    std::cout << "FBX Version " << doc.version << std::endl;
    for(auto & node : doc.nodes) std::cout << node << std::endl;

    auto models = load_models(doc);

    // Compute tangent space basis
    for(auto & m : models)
    {
        for(auto & g : m.geoms)
        {
            for(auto t : g.triangles)
            {
                auto & v0 = g.vertices[t.x], & v1 = g.vertices[t.y], & v2 = g.vertices[t.z];
                const float3 e1 = v1.position - v0.position, e2 = v2.position - v0.position;
                const float2 d1 = v1.texcoord - v0.texcoord, d2 = v2.texcoord - v0.texcoord;
                const float3 dpds = float3(d2.y * e1.x - d1.y * e2.x, d2.y * e1.y - d1.y * e2.y, d2.y * e1.z - d1.y * e2.z) / cross(d1, d2);
                const float3 dpdt = float3(d1.x * e2.x - d2.x * e1.x, d1.x * e2.y - d2.x * e1.y, d1.x * e2.z - d2.x * e1.z) / cross(d1, d2);
                v0.tangent += dpds; v1.tangent += dpds; v2.tangent += dpds;
                v0.bitangent += dpdt; v1.bitangent += dpdt; v2.bitangent += dpdt;
            }
            for(auto & v : g.vertices)
            {
                v.tangent = normalize(v.tangent);
                v.bitangent = normalize(v.bitangent);
            }
        }
    }

    glfwInit();
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_SRGB_CAPABLE, 1);
    auto win = glfwCreateWindow(640, 480, "Example Game", nullptr, nullptr);
    glfwMakeContextCurrent(win);
    glfwSwapInterval(1);
    glewInit();

    GLuint cube_tex;
    glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &cube_tex);
    glTextureStorage2D(cube_tex, 12, GL_SRGB8, 2048, 2048);
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_X, "assets/posx.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, "assets/negx.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, "assets/posy.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, "assets/negy.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, "assets/posz.jpg");
    load_cube_face(cube_tex, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, "assets/negz.jpg");
    glGenerateTextureMipmap(cube_tex);
    glTextureParameteri(cube_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTextureParameteri(cube_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

    auto program = link_program({
        compile_shader(GL_VERTEX_SHADER, R"(#version 450
            uniform mat4 u_model_matrix;
            uniform mat4 u_view_proj_matrix;
            layout(location = 0) in vec3 v_position;
            layout(location = 1) in vec3 v_normal;
            layout(location = 2) in vec2 v_texcoord;
            layout(location = 3) in vec3 v_tangent;
            layout(location = 4) in vec3 v_bitangent;
            out vec3 position;
            out vec3 normal;
            out vec2 texcoord;
            out vec3 tangent;
            out vec3 bitangent;
            void main()
            {
                position = (u_model_matrix * vec4(v_position, 1)).xyz;
                normal = normalize((u_model_matrix * vec4(v_normal, 0)).xyz);
                texcoord = v_texcoord;
                tangent = normalize((u_model_matrix * vec4(v_tangent, 0)).xyz);
                bitangent = normalize((u_model_matrix * vec4(v_bitangent, 0)).xyz);
                gl_Position = u_view_proj_matrix * vec4(position, 1);
            }
        )"),
        compile_shader(GL_FRAGMENT_SHADER, R"(#version 450
            uniform vec3 u_eye_position;
            uniform vec3 u_ambient_light;
            uniform vec3 u_light_direction;
            uniform vec3 u_light_color;
            layout(binding = 0) uniform sampler2D u_albedo;
            layout(binding = 1) uniform sampler2D u_normal;
            layout(binding = 2) uniform sampler2D u_metallic;
            layout(binding = 4) uniform samplerCube u_env;
            in vec3 position;
            in vec3 normal;
            in vec2 texcoord;
            in vec3 tangent;
            in vec3 bitangent;
            layout(location = 0) out vec4 f_color;
            void main()
            {
                vec3 eye_vec = normalize(u_eye_position - position);
                vec3 albedo = texture(u_albedo, texcoord).rgb;
                vec3 tan_normal = normalize(texture(u_normal, texcoord).xyz*2-1);
                vec3 normal_vec = normalize(normalize(tangent)*tan_normal.x + normalize(bitangent)*tan_normal.y + normalize(normal)*tan_normal.z);
                vec3 refl_vec = normal_vec*(dot(eye_vec, normal_vec)*2) - eye_vec;

                vec3 refl_light = albedo * texture(u_env, refl_vec).rgb*2;

                vec3 light = u_ambient_light;

                vec3 light_vec = u_light_direction;
                light += albedo * u_light_color * max(dot(normal_vec, light_vec), 0);
                vec3 half_vec = normalize(light_vec + eye_vec);
                light += u_light_color * pow(max(dot(normal_vec, half_vec), 0), 128);

                float metallic = texture(u_metallic, texcoord).r;

                f_color = vec4(light*(1-metallic) + refl_light*metallic, 1);
            }
        )")
    });

    auto tex_albedo = load_texture("assets/helmet-albedo.jpg", GL_SRGB8);
    auto tex_normal = load_texture("assets/helmet-normal.jpg", GL_RGB8);
    auto tex_metallic = load_texture("assets/helmet-metallic.jpg", GL_R8);

    float3 camera_position {0,0,20};
    float camera_yaw {0}, camera_pitch {0};
    double2 last_cursor;
    auto t0 = std::chrono::high_resolution_clock::now();
    while(!glfwWindowShouldClose(win))
    {
        glfwPollEvents();

        // Compute timestep
        const auto t1 = std::chrono::high_resolution_clock::now();
        const auto timestep = std::chrono::duration<float>(t1 - t0).count();
        t0 = t1;

        // Handle mouselook
        double2 cursor;
        glfwGetCursorPos(win, &cursor.x, &cursor.y);
        if(glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT))
        {
            const auto move = float2(cursor - last_cursor);
            camera_yaw -= move.x * 0.01f;
            camera_pitch = std::max(-1.5f, std::min(1.5f, camera_pitch - move.y * 0.01f));
        }
        last_cursor = cursor;

        // Handle WASD
        const float4 camera_orientation = qmul(rotation_quat(float3{0,1,0}, camera_yaw), rotation_quat(float3{1,0,0}, camera_pitch));
        if(glfwGetKey(win, GLFW_KEY_W)) camera_position -= qzdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_A)) camera_position -= qxdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_S)) camera_position += qzdir(camera_orientation) * (timestep * 50);
        if(glfwGetKey(win, GLFW_KEY_D)) camera_position += qxdir(camera_orientation) * (timestep * 50);

        // Determine matrices
        int width, height;
        glfwGetFramebufferSize(win, &width, &height);
        const auto proj_matrix = linalg::perspective_matrix(1.0f, (float)width/height, 1.0f, 1000.0f);
        const auto view_matrix = inverse(pose_matrix(camera_orientation, camera_position));
        const auto view_proj_matrix = mul(proj_matrix, view_matrix);

        // Clear the viewport
        glEnable(GL_FRAMEBUFFER_SRGB);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glEnable(GL_DEPTH_TEST);
        glUseProgram(program);
        glUniformMatrix4fv(glGetUniformLocation(program, "u_view_proj_matrix"), 1, GL_FALSE, &view_proj_matrix.x.x);
        glUniform3fv(glGetUniformLocation(program, "u_eye_position"), 1, &camera_position.x);

        const float3  ambient_light {0.01f,0.01f,0.01f}, light_direction {normalize(float3{1,5,2})}, light_color {0.8f,0.7f,0.5f};
        glUniform3fv(glGetUniformLocation(program, "u_ambient_light"), 1, &ambient_light.x);
        glUniform3fv(glGetUniformLocation(program, "u_light_direction"), 1, &light_direction.x);
        glUniform3fv(glGetUniformLocation(program, "u_light_color"), 1, &light_color.x);

        for(auto & m : models)
        {
            const auto model_matrix = m.get_model_matrix();
            glUniformMatrix4fv(glGetUniformLocation(program, "u_model_matrix"), 1, GL_FALSE, &model_matrix.x.x);
            glBindTextureUnit(0, tex_albedo);
            glBindTextureUnit(1, tex_normal);
            glBindTextureUnit(2, tex_metallic);
            glBindTextureUnit(4, cube_tex);

            for(auto & g : m.geoms)
            {
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->position);
                glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->normal);
                glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->texcoord);
                glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->tangent);
                glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(fbx::geometry::vertex), &g.vertices.data()->bitangent);
                for(GLuint i : {0,1,2,3,4}) glEnableVertexAttribArray(i);
                glDrawElements(GL_TRIANGLES, g.triangles.size()*3, GL_UNSIGNED_INT, g.triangles.data());
            }
        }

        // Present
        glfwSwapBuffers(win);
    }

    glfwDestroyWindow(win);
    glfwTerminate();
    return EXIT_SUCCESS;
}
catch(const std::exception & e)
{
    std::cerr << "\n" << e.what() << std::endl;
    return EXIT_FAILURE;
}<|endoftext|>


<commit_before>#include <ros/ros.h>
// TODO Include custom message type dock_data_msg
// TODO Include GPS message type
// TODO Include mavlink to/from message types
// TODO Include waypoint list message type

#include "gcs/planPath.h"
#include "gcs/path.h"
#include "gcs/waypoint.h"
#include "gcs/uploadMission.h"
#include "gcs/arm.h"

#define NAME_AS_STRING(macro) #macro
#define VALUE_AS_STRING(macro) NAME_AS_STRING(macro)

#define GCS_CONTROL_CLASS gcs_control

#define SUCCESS					0
#define ERROR_CLEARING_MISSION 	1
#define ERROR_PARAM_SET 		2
#define ERROR_SET_MODE			3

enum gcsState {
	IDLE,
	RECEIVED_DISTRESS_CALL,
	PREPARE,
	WAIT_FOR_READY,
	DEPLOY,
	FLYING,
	ARRIVED
};

enum missionUploadState {
	MISSION_IDLE,
	PATH_RECEIVED,
	UPLOAD_SUCCESS,
	UPLOAD_ERROR
};

class GCS_CONTROL_CLASS
{
	public:
		GCS_CONTROL_CLASS(ros::NodeHandle);
		~GCS_CONTROL_CLASS();
		void run();
	private:
		/* ROS */
		ros::NodeHandle nh;

		ros::ServiceClient plan_path_service_client;
		ros::ServiceClient upload_mission_service_client;
		ros::ServiceClient arm_service_client;

		ros::Subscriber path_subscriber;
		void pathSubscriberCallback(const gcs::path::ConstPtr& msg);

		/* Methods */

		/* Attributes */
		gcsState state = IDLE;
		missionUploadState mission_upload_state = MISSION_IDLE;
		gcs::path planned_path;

	// 1 Monitor docking station
	// - Call service monitorDock() from docking_station_node
	// TODO

	// 2 Receive distress call from database
	// - Http get GPS position and timestamp from database
	// TODO

	// 3 Initiate pre-flight check
	// - Call service preflight() from pre_flight_node
	// TODO

	// 4 Perform path planning
	// - Call service planPath() from path_planner_node
	// TODO

	// 5 Open docking station
	// - Call service openDock() from docking_station_node
	// TODO

	// 6 Upload path to drone and initiate flight
	// - Call service uploadWaypoints() from drone_communication_node
	// TODO

	// 7 Monitor the flight (Error procedure)
	// - Call service monitorFlight() from drone_communication_node subscribing to mavlink/from
	// - In case of extended link loss, do something
	// TODO

	// 8 Update database
	// - Http post flight information (heartbeat, battery voltage, etc.) to database
	// TODO

};

GCS_CONTROL_CLASS::GCS_CONTROL_CLASS(ros::NodeHandle n)
{
	nh = n;

	plan_path_service_client = nh.serviceClient<gcs::planPath>("/path_planner/plan");
	upload_mission_service_client = nh.serviceClient<gcs::uploadMission>("/drone_communication/uploadMission");
	arm_service_client = nh.serviceClient<gcs::arm>("/drone_communication/arm");

	path_subscriber = nh.subscribe<gcs::path>("/path_planer/path",1,&GCS_CONTROL_CLASS::pathSubscriberCallback,this);

}

void GCS_CONTROL_CLASS::run()
{
	switch (state)
	{
		case IDLE:
			{
				// Continuosly monitor drone and docking station
			}
			break;
		case RECEIVED_DISTRESS_CALL:
			{
				// Start preflight check

				// Start path planning
				gcs::planPath path_request;
				path_request.request.origin.lat = 55.0;
				path_request.request.origin.lon = 10.0;
				path_request.request.origin.alt = 10.0;
				path_request.request.goal.lat = 55.5;
				path_request.request.goal.lon = 10.0;
				path_request.request.goal.alt = 10.0;
				if ( !plan_path_service_client.call(path_request) )
					ROS_ERROR("Plan path failed");
				state = PREPARE;
			}
			break;
		case PREPARE:
			{
				if( mission_upload_state == PATH_RECEIVED )
				{
					gcs::uploadMission mission_upload_msg;
					mission_upload_msg.request.waypoints = planned_path;
					if( upload_mission_service_client.call(mission_upload_msg) && mission_upload_msg.response.result == SUCCESS )
					{
						mission_upload_state = UPLOAD_SUCCESS;
					}
					else
					{
						mission_upload_state = UPLOAD_ERROR;
						ROS_ERROR("Failed to upload mission");
					}
				}
				// if weather ok, open docking station
				if(mission_upload_state == UPLOAD_SUCCESS ) // and weather ok
				{
					state = WAIT_FOR_READY;
				}
			}
			break;
		case WAIT_FOR_READY:
			{
				// wait for opening of docking station
				state = DEPLOY;
			}
			break;
		case DEPLOY:
			{
				//If everything ok -> arm the drone
				gcs::arm arm_msg;
				if( arm_service_client.call(arm_msg) && arm_msg.response.result == SUCCESS)
				{
					state = FLYING;
				}
				else
					ROS_ERROR("Failed to arm");
			}
			break;
		case FLYING:
			{
				// Monitor during flight
			}
			break;
		case ARRIVED:
			{
				// ?
			}
			break;
		default:
			ROS_ERROR("Bad state");
			/* Default Code */
	}

}

void GCS_CONTROL_CLASS::pathSubscriberCallback(const gcs::path::ConstPtr& msg)
{
	planned_path = *msg;
	mission_upload_state = PATH_RECEIVED;
}

GCS_CONTROL_CLASS::~GCS_CONTROL_CLASS()
{}

int main(int argc, char** argv)
{
	ros::init(argc, argv, VALUE_AS_STRING(GCS_CONTROL_CLASS));
	ros::NodeHandle nh;
	GCS_CONTROL_CLASS gcs(nh);
	ros::Rate rate(20);
	while(ros::ok())
	{
		gcs.run();
		ros::spinOnce();
	}
	return 0;
}
<commit_msg>Added rate in gcs_control_node<commit_after>#include <ros/ros.h>
// TODO Include custom message type dock_data_msg
// TODO Include GPS message type
// TODO Include mavlink to/from message types
// TODO Include waypoint list message type

#include "gcs/planPath.h"
#include "gcs/path.h"
#include "gcs/waypoint.h"
#include "gcs/uploadMission.h"
#include "gcs/arm.h"

#define NAME_AS_STRING(macro) #macro
#define VALUE_AS_STRING(macro) NAME_AS_STRING(macro)

#define GCS_CONTROL_CLASS gcs_control

#define SUCCESS					0
#define ERROR_CLEARING_MISSION 	1
#define ERROR_PARAM_SET 		2
#define ERROR_SET_MODE			3

enum gcsState {
	IDLE,
	RECEIVED_DISTRESS_CALL,
	PREPARE,
	WAIT_FOR_READY,
	DEPLOY,
	FLYING,
	ARRIVED
};

enum missionUploadState {
	MISSION_IDLE,
	PATH_RECEIVED,
	UPLOAD_SUCCESS,
	UPLOAD_ERROR
};

class GCS_CONTROL_CLASS
{
	public:
		GCS_CONTROL_CLASS(ros::NodeHandle);
		~GCS_CONTROL_CLASS();
		void run();
	private:
		/* ROS */
		ros::NodeHandle nh;

		ros::ServiceClient plan_path_service_client;
		ros::ServiceClient upload_mission_service_client;
		ros::ServiceClient arm_service_client;

		ros::Subscriber path_subscriber;
		void pathSubscriberCallback(const gcs::path::ConstPtr& msg);

		/* Methods */

		/* Attributes */
		gcsState state = IDLE;
		missionUploadState mission_upload_state = MISSION_IDLE;
		gcs::path planned_path;

	// 1 Monitor docking station
	// - Call service monitorDock() from docking_station_node
	// TODO

	// 2 Receive distress call from database
	// - Http get GPS position and timestamp from database
	// TODO

	// 3 Initiate pre-flight check
	// - Call service preflight() from pre_flight_node
	// TODO

	// 4 Perform path planning
	// - Call service planPath() from path_planner_node
	// TODO

	// 5 Open docking station
	// - Call service openDock() from docking_station_node
	// TODO

	// 6 Upload path to drone and initiate flight
	// - Call service uploadWaypoints() from drone_communication_node
	// TODO

	// 7 Monitor the flight (Error procedure)
	// - Call service monitorFlight() from drone_communication_node subscribing to mavlink/from
	// - In case of extended link loss, do something
	// TODO

	// 8 Update database
	// - Http post flight information (heartbeat, battery voltage, etc.) to database
	// TODO

};

GCS_CONTROL_CLASS::GCS_CONTROL_CLASS(ros::NodeHandle n)
{
	nh = n;

	plan_path_service_client = nh.serviceClient<gcs::planPath>("/path_planner/plan");
	upload_mission_service_client = nh.serviceClient<gcs::uploadMission>("/drone_communication/uploadMission");
	arm_service_client = nh.serviceClient<gcs::arm>("/drone_communication/arm");

	path_subscriber = nh.subscribe<gcs::path>("/path_planer/path",1,&GCS_CONTROL_CLASS::pathSubscriberCallback,this);

}

void GCS_CONTROL_CLASS::run()
{
	switch (state)
	{
		case IDLE:
			{
				// Continuosly monitor drone and docking station
			}
			break;
		case RECEIVED_DISTRESS_CALL:
			{
				// Start preflight check

				// Start path planning
				gcs::planPath path_request;
				path_request.request.origin.lat = 55.0;
				path_request.request.origin.lon = 10.0;
				path_request.request.origin.alt = 10.0;
				path_request.request.goal.lat = 55.5;
				path_request.request.goal.lon = 10.0;
				path_request.request.goal.alt = 10.0;
				if ( !plan_path_service_client.call(path_request) )
					ROS_ERROR("Plan path failed");
				state = PREPARE;
			}
			break;
		case PREPARE:
			{
				if( mission_upload_state == PATH_RECEIVED )
				{
					gcs::uploadMission mission_upload_msg;
					mission_upload_msg.request.waypoints = planned_path;
					if( upload_mission_service_client.call(mission_upload_msg) && mission_upload_msg.response.result == SUCCESS )
					{
						mission_upload_state = UPLOAD_SUCCESS;
					}
					else
					{
						mission_upload_state = UPLOAD_ERROR;
						ROS_ERROR("Failed to upload mission");
					}
				}
				// if weather ok, open docking station
				if(mission_upload_state == UPLOAD_SUCCESS ) // and weather ok
				{
					state = WAIT_FOR_READY;
				}
			}
			break;
		case WAIT_FOR_READY:
			{
				// wait for opening of docking station
				state = DEPLOY;
			}
			break;
		case DEPLOY:
			{
				//If everything ok -> arm the drone
				gcs::arm arm_msg;
				if( arm_service_client.call(arm_msg) && arm_msg.response.result == SUCCESS)
				{
					state = FLYING;
				}
				else
					ROS_ERROR("Failed to arm");
			}
			break;
		case FLYING:
			{
				// Monitor during flight
			}
			break;
		case ARRIVED:
			{
				// ?
			}
			break;
		default:
			ROS_ERROR("Bad state");
			/* Default Code */
	}

}

void GCS_CONTROL_CLASS::pathSubscriberCallback(const gcs::path::ConstPtr& msg)
{
	planned_path = *msg;
	mission_upload_state = PATH_RECEIVED;
}

GCS_CONTROL_CLASS::~GCS_CONTROL_CLASS()
{}

int main(int argc, char** argv)
{
	ros::init(argc, argv, VALUE_AS_STRING(GCS_CONTROL_CLASS));
	ros::NodeHandle nh;
	GCS_CONTROL_CLASS gcs(nh);
	ros::Rate rate(20);
	while(ros::ok())
	{
		gcs.run();
		ros::spinOnce();
		rate.sleep();
	}
	return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_HPP

#define MAPNIK_MAJOR_VERSION 3
#define MAPNIK_MINOR_VERSION 0
#define MAPNIK_PATCH_VERSION 9

#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)

#ifndef MAPNIK_STRINGIFY
#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n)
#define MAPNIK_STRINGIFY_HELPER(n) #n
#endif

#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION)

#endif // MAPNIK_VERSION_HPP
<commit_msg>setting up for mapnik v3.0.10 release [skip ci]<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_HPP

#define MAPNIK_MAJOR_VERSION 3
#define MAPNIK_MINOR_VERSION 0
#define MAPNIK_PATCH_VERSION 10

#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)

#ifndef MAPNIK_STRINGIFY
#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n)
#define MAPNIK_STRINGIFY_HELPER(n) #n
#endif

#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION)

#endif // MAPNIK_VERSION_HPP
<|endoftext|>