<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/memory_details.h"

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <set>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/process_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/process_type.h"
#include "grit/chromium_strings.h"
#include "ui/base/l10n/l10n_util.h"

using base::ProcessEntry;
using content::BrowserThread;

// Known browsers which we collect details for.
enum BrowserType {
  CHROME = 0,
  FIREFOX,
  ICEWEASEL,
  OPERA,
  KONQUEROR,
  EPIPHANY,
  MIDORI,
  MAX_BROWSERS
} BrowserProcess;

// The pretty printed names of those browsers. Matches up with enum
// BrowserType.
static const char kBrowserPrettyNames[][10] = {
  "Chrome",
  "Firefox",
  "Iceweasel",
  "Opera",
  "Konqueror",
  "Epiphany",
  "Midori",
};

// A mapping from process name to the type of browser.
static const struct {
  const char process_name[16];
  BrowserType browser;
} kBrowserBinaryNames[] = {
  { "firefox", FIREFOX },
  { "firefox-3.5", FIREFOX },
  { "firefox-3.0", FIREFOX },
  { "firefox-bin", FIREFOX },
  { "iceweasel", ICEWEASEL },
  { "opera", OPERA },
  { "konqueror", KONQUEROR },
  { "epiphany-browse", EPIPHANY },
  { "epiphany", EPIPHANY },
  { "midori", MIDORI },
  { "", MAX_BROWSERS },
};

MemoryDetails::MemoryDetails()
    : user_metrics_mode_(UPDATE_USER_METRICS) {
}

ProcessData* MemoryDetails::ChromeBrowser() {
  return &process_data_[0];
}

struct Process {
  pid_t pid;
  pid_t parent;
  std::string name;
};

typedef std::map<pid_t, Process> ProcessMap;

// Get information on all the processes running on the system.
static ProcessMap GetProcesses() {
  ProcessMap map;

  base::ProcessIterator process_iter(NULL);
  while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
    Process process;
    process.pid = process_entry->pid();
    process.parent = process_entry->parent_pid();
    process.name = process_entry->exe_file();
    map.insert(std::make_pair(process.pid, process));
  }
  return map;
}

// Given a process name, return the type of the browser which created that
// process, or |MAX_BROWSERS| if we don't know about it.
static BrowserType GetBrowserType(const std::string& process_name) {
  for (unsigned i = 0; kBrowserBinaryNames[i].process_name[0]; ++i) {
    if (strcmp(process_name.c_str(), kBrowserBinaryNames[i].process_name) == 0)
      return kBrowserBinaryNames[i].browser;
  }

  return MAX_BROWSERS;
}

// For each of a list of pids, collect memory information about that process.
static ProcessData GetProcessDataMemoryInformation(
    const std::vector<pid_t>& pids) {
  ProcessData process_data;
  for (std::vector<pid_t>::const_iterator iter = pids.begin();
       iter != pids.end();
       ++iter) {
    ProcessMemoryInformation pmi;

    pmi.pid = *iter;
    pmi.num_processes = 1;

    if (pmi.pid == base::GetCurrentProcId())
      pmi.process_type = content::PROCESS_TYPE_BROWSER;
    else
      pmi.process_type = content::PROCESS_TYPE_UNKNOWN;

    base::ProcessMetrics* metrics =
        base::ProcessMetrics::CreateProcessMetrics(*iter);
    metrics->GetWorkingSetKBytes(&pmi.working_set);
    delete metrics;

    process_data.processes.push_back(pmi);
  }
  return process_data;
}

// Find all children of the given process with pid |root|.
static std::vector<pid_t> GetAllChildren(const ProcessMap& processes,
                                         const pid_t root) {
  std::vector<pid_t> children;
  children.push_back(root);

  std::set<pid_t> wavefront, next_wavefront;
  wavefront.insert(root);

  while (wavefront.size()) {
    for (ProcessMap::const_iterator iter = processes.begin();
         iter != processes.end();
         ++iter) {
      const Process& process = iter->second;
      if (wavefront.count(process.parent)) {
        children.push_back(process.pid);
        next_wavefront.insert(process.pid);
      }
    }

    wavefront.clear();
    wavefront.swap(next_wavefront);
  }
  return children;
}

#if defined(OS_CHROMEOS)
static uint64 ReadFileToUint64(const base::FilePath file) {
  std::string file_as_string;
  if (!file_util::ReadFileToString(file, &file_as_string))
    return 0;
  uint64 file_as_uint64;
  if (!base::StringToUint64(file_as_string, &file_as_uint64))
    return 0;
  return file_as_uint64;
}

static void GetSwapData(SwapData* swap_data) {
  base::FilePath zram_path("/sys/block/zram0");
  uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size"));
  if (orig_data_size <= 4096) {
    // A single page is compressed at startup, and has a high compression
    // ratio. We ignore this as it doesn't indicate any real swapping.
    swap_data->orig_data_size = 0;
    swap_data->num_reads = 0;
    swap_data->num_writes = 0;
    swap_data->compr_data_size = 0;
    swap_data->mem_used_total = 0;
  }
  swap_data->orig_data_size = orig_data_size;
  swap_data->num_reads = ReadFileToUint64(zram_path.Append("num_reads"));
  swap_data->num_writes = ReadFileToUint64(zram_path.Append("num_writes"));
  swap_data->compr_data_size =
      ReadFileToUint64(zram_path.Append("compr_data_size"));
  swap_data->mem_used_total =
      ReadFileToUint64(zram_path.Append("mem_used_total"));
}
#endif

void MemoryDetails::CollectProcessData(
    const std::vector<ProcessMemoryInformation>& child_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  ProcessMap process_map = GetProcesses();
  std::set<pid_t> browsers_found;

  // For each process on the system, if it appears to be a browser process and
  // it's parent isn't a browser process, then record it in |browsers_found|.
  for (ProcessMap::const_iterator iter = process_map.begin();
       iter != process_map.end();
       ++iter) {
    const Process& current_process = iter->second;
    const BrowserType type = GetBrowserType(current_process.name);
    if (type == MAX_BROWSERS)
      continue;

    ProcessMap::const_iterator parent_iter =
        process_map.find(current_process.parent);
    if (parent_iter == process_map.end()) {
      browsers_found.insert(current_process.pid);
      continue;
    }

    if (GetBrowserType(parent_iter->second.name) != type) {
      // We found a process whose type is diffent from its parent's type.
      // That means it is the root process of the browser.
      browsers_found.insert(current_process.pid);
      break;
    }
  }

  ProcessData current_browser =
      GetProcessDataMemoryInformation(GetAllChildren(process_map, getpid()));
  current_browser.name = l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
  current_browser.process_name = ASCIIToUTF16("chrome");

  for (std::vector<ProcessMemoryInformation>::iterator
       i = current_browser.processes.begin();
       i != current_browser.processes.end(); ++i) {
    // Check if this is one of the child processes whose data we collected
    // on the IO thread, and if so copy over that data.
    for (size_t child = 0; child < child_info.size(); child++) {
      if (child_info[child].pid != i->pid)
        continue;
      i->titles = child_info[child].titles;
      i->process_type = child_info[child].process_type;
      break;
    }
  }

  process_data_.push_back(current_browser);

  // For each browser process, collect a list of its children and get the
  // memory usage of each.
  for (std::set<pid_t>::const_iterator iter = browsers_found.begin();
       iter != browsers_found.end();
       ++iter) {
    std::vector<pid_t> browser_processes = GetAllChildren(process_map, *iter);
    ProcessData browser = GetProcessDataMemoryInformation(browser_processes);

    ProcessMap::const_iterator process_iter = process_map.find(*iter);
    if (process_iter == process_map.end())
      continue;
    BrowserType type = GetBrowserType(process_iter->second.name);
    if (type != MAX_BROWSERS)
      browser.name = ASCIIToUTF16(kBrowserPrettyNames[type]);
    process_data_.push_back(browser);
  }

#if defined(OS_CHROMEOS)
  GetSwapData(&swap_data_);
#endif

  // Finally return to the browser thread.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
}
<commit_msg>Ensure that we ignore initial swap state.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/memory_details.h"

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <set>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/process_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/process_type.h"
#include "grit/chromium_strings.h"
#include "ui/base/l10n/l10n_util.h"

using base::ProcessEntry;
using content::BrowserThread;

// Known browsers which we collect details for.
enum BrowserType {
  CHROME = 0,
  FIREFOX,
  ICEWEASEL,
  OPERA,
  KONQUEROR,
  EPIPHANY,
  MIDORI,
  MAX_BROWSERS
} BrowserProcess;

// The pretty printed names of those browsers. Matches up with enum
// BrowserType.
static const char kBrowserPrettyNames[][10] = {
  "Chrome",
  "Firefox",
  "Iceweasel",
  "Opera",
  "Konqueror",
  "Epiphany",
  "Midori",
};

// A mapping from process name to the type of browser.
static const struct {
  const char process_name[16];
  BrowserType browser;
} kBrowserBinaryNames[] = {
  { "firefox", FIREFOX },
  { "firefox-3.5", FIREFOX },
  { "firefox-3.0", FIREFOX },
  { "firefox-bin", FIREFOX },
  { "iceweasel", ICEWEASEL },
  { "opera", OPERA },
  { "konqueror", KONQUEROR },
  { "epiphany-browse", EPIPHANY },
  { "epiphany", EPIPHANY },
  { "midori", MIDORI },
  { "", MAX_BROWSERS },
};

MemoryDetails::MemoryDetails()
    : user_metrics_mode_(UPDATE_USER_METRICS) {
}

ProcessData* MemoryDetails::ChromeBrowser() {
  return &process_data_[0];
}

struct Process {
  pid_t pid;
  pid_t parent;
  std::string name;
};

typedef std::map<pid_t, Process> ProcessMap;

// Get information on all the processes running on the system.
static ProcessMap GetProcesses() {
  ProcessMap map;

  base::ProcessIterator process_iter(NULL);
  while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
    Process process;
    process.pid = process_entry->pid();
    process.parent = process_entry->parent_pid();
    process.name = process_entry->exe_file();
    map.insert(std::make_pair(process.pid, process));
  }
  return map;
}

// Given a process name, return the type of the browser which created that
// process, or |MAX_BROWSERS| if we don't know about it.
static BrowserType GetBrowserType(const std::string& process_name) {
  for (unsigned i = 0; kBrowserBinaryNames[i].process_name[0]; ++i) {
    if (strcmp(process_name.c_str(), kBrowserBinaryNames[i].process_name) == 0)
      return kBrowserBinaryNames[i].browser;
  }

  return MAX_BROWSERS;
}

// For each of a list of pids, collect memory information about that process.
static ProcessData GetProcessDataMemoryInformation(
    const std::vector<pid_t>& pids) {
  ProcessData process_data;
  for (std::vector<pid_t>::const_iterator iter = pids.begin();
       iter != pids.end();
       ++iter) {
    ProcessMemoryInformation pmi;

    pmi.pid = *iter;
    pmi.num_processes = 1;

    if (pmi.pid == base::GetCurrentProcId())
      pmi.process_type = content::PROCESS_TYPE_BROWSER;
    else
      pmi.process_type = content::PROCESS_TYPE_UNKNOWN;

    base::ProcessMetrics* metrics =
        base::ProcessMetrics::CreateProcessMetrics(*iter);
    metrics->GetWorkingSetKBytes(&pmi.working_set);
    delete metrics;

    process_data.processes.push_back(pmi);
  }
  return process_data;
}

// Find all children of the given process with pid |root|.
static std::vector<pid_t> GetAllChildren(const ProcessMap& processes,
                                         const pid_t root) {
  std::vector<pid_t> children;
  children.push_back(root);

  std::set<pid_t> wavefront, next_wavefront;
  wavefront.insert(root);

  while (wavefront.size()) {
    for (ProcessMap::const_iterator iter = processes.begin();
         iter != processes.end();
         ++iter) {
      const Process& process = iter->second;
      if (wavefront.count(process.parent)) {
        children.push_back(process.pid);
        next_wavefront.insert(process.pid);
      }
    }

    wavefront.clear();
    wavefront.swap(next_wavefront);
  }
  return children;
}

#if defined(OS_CHROMEOS)
static uint64 ReadFileToUint64(const base::FilePath file) {
  std::string file_as_string;
  if (!file_util::ReadFileToString(file, &file_as_string))
    return 0;
  uint64 file_as_uint64;
  if (!base::StringToUint64(file_as_string, &file_as_uint64))
    return 0;
  return file_as_uint64;
}

static void GetSwapData(SwapData* swap_data) {
  base::FilePath zram_path("/sys/block/zram0");
  uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size"));
  if (orig_data_size <= 4096) {
    // A single page is compressed at startup, and has a high compression
    // ratio. We ignore this as it doesn't indicate any real swapping.
    swap_data->orig_data_size = 0;
    swap_data->num_reads = 0;
    swap_data->num_writes = 0;
    swap_data->compr_data_size = 0;
    swap_data->mem_used_total = 0;
    return;
  }
  swap_data->orig_data_size = orig_data_size;
  swap_data->num_reads = ReadFileToUint64(zram_path.Append("num_reads"));
  swap_data->num_writes = ReadFileToUint64(zram_path.Append("num_writes"));
  swap_data->compr_data_size =
      ReadFileToUint64(zram_path.Append("compr_data_size"));
  swap_data->mem_used_total =
      ReadFileToUint64(zram_path.Append("mem_used_total"));
}
#endif

void MemoryDetails::CollectProcessData(
    const std::vector<ProcessMemoryInformation>& child_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  ProcessMap process_map = GetProcesses();
  std::set<pid_t> browsers_found;

  // For each process on the system, if it appears to be a browser process and
  // it's parent isn't a browser process, then record it in |browsers_found|.
  for (ProcessMap::const_iterator iter = process_map.begin();
       iter != process_map.end();
       ++iter) {
    const Process& current_process = iter->second;
    const BrowserType type = GetBrowserType(current_process.name);
    if (type == MAX_BROWSERS)
      continue;

    ProcessMap::const_iterator parent_iter =
        process_map.find(current_process.parent);
    if (parent_iter == process_map.end()) {
      browsers_found.insert(current_process.pid);
      continue;
    }

    if (GetBrowserType(parent_iter->second.name) != type) {
      // We found a process whose type is diffent from its parent's type.
      // That means it is the root process of the browser.
      browsers_found.insert(current_process.pid);
      break;
    }
  }

  ProcessData current_browser =
      GetProcessDataMemoryInformation(GetAllChildren(process_map, getpid()));
  current_browser.name = l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
  current_browser.process_name = ASCIIToUTF16("chrome");

  for (std::vector<ProcessMemoryInformation>::iterator
       i = current_browser.processes.begin();
       i != current_browser.processes.end(); ++i) {
    // Check if this is one of the child processes whose data we collected
    // on the IO thread, and if so copy over that data.
    for (size_t child = 0; child < child_info.size(); child++) {
      if (child_info[child].pid != i->pid)
        continue;
      i->titles = child_info[child].titles;
      i->process_type = child_info[child].process_type;
      break;
    }
  }

  process_data_.push_back(current_browser);

  // For each browser process, collect a list of its children and get the
  // memory usage of each.
  for (std::set<pid_t>::const_iterator iter = browsers_found.begin();
       iter != browsers_found.end();
       ++iter) {
    std::vector<pid_t> browser_processes = GetAllChildren(process_map, *iter);
    ProcessData browser = GetProcessDataMemoryInformation(browser_processes);

    ProcessMap::const_iterator process_iter = process_map.find(*iter);
    if (process_iter == process_map.end())
      continue;
    BrowserType type = GetBrowserType(process_iter->second.name);
    if (type != MAX_BROWSERS)
      browser.name = ASCIIToUTF16(kBrowserPrettyNames[type]);
    process_data_.push_back(browser);
  }

#if defined(OS_CHROMEOS)
  GetSwapData(&swap_data_);
#endif

  // Finally return to the browser thread.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
}
<|endoftext|>


<commit_before>#include <Core/Engine.h>
#include <Core/Resources.h>
#include <Core/World.h>
#include <Core/Device.h>
#include <Input/Input.h>
#include <Audio/Audio.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <imgui/imgui_impl_glfw_gl3.h>
#include <Tools/Profiler.h>
#include <cereal/archives/json.hpp>
#include <fstream>

using namespace Osm;
using namespace std;

CEngine Osm::Engine;

void EngineSettings::LoadFromFile(const std::string& file)
{
	FilePath = file;
	ifstream fs;
	fs.open(FilePath);
	if (fs.is_open())
	{
		cereal::JSONInputArchive iarchive(fs);
		iarchive(cereal::make_nvp("Setttings", *this));
	}
	fs.close();
}

void EngineSettings::SaveToFile()
{
	ofstream fs;
	fs.open(FilePath);

	{
		cereal::JSONOutputArchive oarchive(fs);
		oarchive(cereal::make_nvp("Setttings", *this));
	}
	fs.close();
}

void EngineSettings::Inspect()
{
	ImGui::SliderInt("Screen Width", &ScreenWidth, 320, 5600);
	ImGui::SliderInt("Screen Height", &ScreenHeight, 240, 5600);
	ImGui::Checkbox("Full Screen", &FullScreen);
	ImGui::Checkbox("Native Resolution", &UseNativeResolution);
	ImGui::SliderFloat("Inspector Font Size", &InspectorFontSize, 0.5f, 2.0f);

	if (ImGui::Button("Save Globals"))
	{
		SaveToFile();
	}
}

void CEngine::InitializeInternal()
{
	_initialized = true;

	_resources = CreateComponent<ResourceManager>();

	_device = CreateComponent<GraphicsDevice>();

	_input = CreateComponent<InputManager>();

	_profiler = CreateComponent<Profiler>();

	_audio = CreateComponent<AudioManager>();

	ImGui_ImplGlfwGL3_Init(_device->GetWindow(), true);
}

void CEngine::Initialize(const EngineSettings& options)
{
	_settings = options;
	InitializeInternal();
}

void CEngine::Shutdown()
{
	ASSERT(_initialized);

	// Remove component in the reverse order they were created
	while (_components.size() != 0)
		_components.erase(_components.end() - 1);
}

void CEngine::Run()
{
	ASSERT(_initialized);

	auto lastFrame = glfwGetTime();
	while (!glfwWindowShouldClose(_device->GetWindow()) ||
			glfwGetKey(_device->GetWindow(), GLFW_KEY_ESCAPE))
	{
		glfwPollEvents();

		if (_event)
		{
			_event();
			_event = nullptr;
		}

		if (!_world)
			continue;

		auto currentFrame = glfwGetTime();
		float deltaTime = (float)(currentFrame - lastFrame);
		lastFrame = currentFrame;
		if (deltaTime > 0.033f)
			deltaTime = 0.033f;

		// Update
		if (!_paused || _advanceFrame)
		{
			_profiler->StartFrame();
			uint updateID = _profiler->StartSection("Update");
			_input->Update();
			_world->Update(deltaTime);
			_profiler->EndSection(updateID);
			_advanceFrame = false;
		}

		uint renderID = _profiler->StartSection("Render");
		glViewport(0, 0, _device->GetScreenWidth(), _device->GetScreenHeight());
		_world->Render();
		_profiler->EndSection(renderID);

#ifdef INSPECTOR
		Inspect();
#endif

		glfwSwapBuffers(_device->GetWindow());
	}
}

void CEngine::SwapWorld(World* world)
{
	QueueEvent([this, world]()
	{
		if (_world)
			delete _world;
		_world = world;
	});
}

#ifdef INSPECTOR
void CEngine::Inspect()
{
	ImGui::GetIO().FontGlobalScale = _settings.InspectorFontSize;

	ImGuiWindowFlags window_flags = 0;
	//window_flags |= ImGuiWindowFlags_NoTitleBar;
	window_flags |= ImGuiWindowFlags_MenuBar;

	ImGui_ImplGlfwGL3_NewFrame();

	bool p_open = true;

	ImGui::BeginMainMenuBar();
	{
		{
			if (ImGui::BeginMenu("Tools"))
			{
				ImGui::MenuItem("Engine Inspector", nullptr, &_show_engine_compoents);
				// Just a reminder that this might be useful
				// ImGui::MenuItem("Console", NULL, &show_app_console);
				// ImGui::MenuItem("Log", NULL, &show_app_log);
				// ImGui::MenuItem("Input Debugger", nullptr, &_show_input_debug);
				ImGui::MenuItem("World Inspector", nullptr, &_show_world_inspector);
				ImGui::MenuItem("Settings Inspector", nullptr, &_show_settings);
				ImGui::MenuItem("Profiler", nullptr, &_show_profiler);
				ImGui::MenuItem("ImGui Test", nullptr, &_show_imgui_test);
				ImGui::EndMenu();
			}
		}

		// Paused button
		if (!_paused)
			_paused = ImGui::Button("||");
		else
			_paused = !ImGui::Button("[>");
		ImGui::SameLine();
		_advanceFrame = ImGui::Button(">|");
	}
	ImGui::EndMainMenuBar();

	if (_show_world_inspector)
	{
		ImGui::Begin("World Inspector");
		_world->Inspect();
		ImGui::End();
	}

	if(_show_profiler)
	{
		_profiler->Inspect();
	}

	if (_show_imgui_test)
	{
		ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
		ImGui::ShowTestWindow(&_show_imgui_test);
	}

	if(_show_engine_compoents)
	{
		ImGui::Begin("Engine Inspector");
		for (auto& c : _components)
		{
			string name = typeid(*c).name();
			name = StringReplace(name, "class ", "");
			if (ImGui::CollapsingHeader(name.c_str()))
			{
				c->Inspect();
			}
		}
		ImGui::End();
	}

	if (_show_settings)
	{
		ImGui::Begin("Settings Inspector");
		_settings.Inspect();
		ImGui::End();
	}

	ImGui::Render();
}
#endif

/*
void CEngine::Update()
{
	ASSERT(_initialized);
}

void CEngine::Render()
{
	ASSERT(_initialized);
}
*/<commit_msg>[WIP] Performance bar<commit_after>#include <Core/Engine.h>
#include <Core/Resources.h>
#include <Core/World.h>
#include <Core/Device.h>
#include <Input/Input.h>
#include <Audio/Audio.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <imgui/imgui_impl_glfw_gl3.h>
#include <Tools/Profiler.h>
#include <cereal/archives/json.hpp>
#include <fstream>

using namespace Osm;
using namespace std;

CEngine Osm::Engine;

void EngineSettings::LoadFromFile(const std::string& file)
{
	FilePath = file;
	ifstream fs;
	fs.open(FilePath);
	if (fs.is_open())
	{
		cereal::JSONInputArchive iarchive(fs);
		iarchive(cereal::make_nvp("Setttings", *this));
	}
	fs.close();
}

void EngineSettings::SaveToFile()
{
	ofstream fs;
	fs.open(FilePath);

	{
		cereal::JSONOutputArchive oarchive(fs);
		oarchive(cereal::make_nvp("Setttings", *this));
	}
	fs.close();
}

void EngineSettings::Inspect()
{
	ImGui::SliderInt("Screen Width", &ScreenWidth, 320, 5600);
	ImGui::SliderInt("Screen Height", &ScreenHeight, 240, 5600);
	ImGui::Checkbox("Full Screen", &FullScreen);
	ImGui::Checkbox("Native Resolution", &UseNativeResolution);
	ImGui::SliderFloat("Inspector Font Size", &InspectorFontSize, 0.5f, 2.0f);

	if (ImGui::Button("Save Globals"))
	{
		SaveToFile();
	}
}

void CEngine::InitializeInternal()
{
	_initialized = true;

	_resources = CreateComponent<ResourceManager>();

	_device = CreateComponent<GraphicsDevice>();

	_input = CreateComponent<InputManager>();

	_profiler = CreateComponent<Profiler>();

	_audio = CreateComponent<AudioManager>();

	ImGui_ImplGlfwGL3_Init(_device->GetWindow(), true);
}

void CEngine::Initialize(const EngineSettings& options)
{
	_settings = options;
	InitializeInternal();
}

void CEngine::Shutdown()
{
	ASSERT(_initialized);

	// Remove component in the reverse order they were created
	while (_components.size() != 0)
		_components.erase(_components.end() - 1);
}

void CEngine::Run()
{
	ASSERT(_initialized);

	auto lastFrame = glfwGetTime();
	while (!glfwWindowShouldClose(_device->GetWindow()) ||
			glfwGetKey(_device->GetWindow(), GLFW_KEY_ESCAPE))
	{
		glfwPollEvents();

		if (_event)
		{
			_event();
			_event = nullptr;
		}

		if (!_world)
			continue;

		auto currentFrame = glfwGetTime();
		float deltaTime = (float)(currentFrame - lastFrame);
		lastFrame = currentFrame;
		if (deltaTime > 0.033f)
			deltaTime = 0.033f;

		// Update
		if (!_paused || _advanceFrame)
		{
			_profiler->StartFrame();
			uint updateID = _profiler->StartSection("Update");
			_input->Update();
			_world->Update(deltaTime);
			_profiler->EndSection(updateID);
			_advanceFrame = false;
		}

		uint renderID = _profiler->StartSection("Render");
		glViewport(0, 0, _device->GetScreenWidth(), _device->GetScreenHeight());
		_world->Render();
		_profiler->EndSection(renderID);

#ifdef INSPECTOR
		Inspect();
#endif

		glfwSwapBuffers(_device->GetWindow());
	}
}

void CEngine::SwapWorld(World* world)
{
	QueueEvent([this, world]()
	{
		if (_world)
			delete _world;
		_world = world;
	});
}

#ifdef INSPECTOR
void CEngine::Inspect()
{
	ImGui::GetIO().FontGlobalScale = _settings.InspectorFontSize;

	ImGuiWindowFlags window_flags = 0;
	//window_flags |= ImGuiWindowFlags_NoTitleBar;
	window_flags |= ImGuiWindowFlags_MenuBar;

	ImGui_ImplGlfwGL3_NewFrame();

	bool p_open = true;

	ImGui::BeginMainMenuBar();
	{
		{
			if (ImGui::BeginMenu("Tools"))
			{
				ImGui::MenuItem("Engine Inspector", nullptr, &_show_engine_compoents);
				// Just a reminder that this might be useful
				// ImGui::MenuItem("Console", NULL, &show_app_console);
				// ImGui::MenuItem("Log", NULL, &show_app_log);
				// ImGui::MenuItem("Input Debugger", nullptr, &_show_input_debug);
				ImGui::MenuItem("World Inspector", nullptr, &_show_world_inspector);
				ImGui::MenuItem("Settings Inspector", nullptr, &_show_settings);
				ImGui::MenuItem("Profiler", nullptr, &_show_profiler);
				ImGui::MenuItem("ImGui Test", nullptr, &_show_imgui_test);
				ImGui::EndMenu();
			}
		}

		// Paused button
		if (!_paused)
			_paused = ImGui::Button("||");
		else
			_paused = !ImGui::Button("[>");
		ImGui::SameLine();
		_advanceFrame = ImGui::Button(">|");

		ImGui::SameLine();
		ImGui::LabelText("Usage", "");
		ImGui::SameLine();
		ImGui::ProgressBar(0.95f);
		//ImGui::ProgressBar(0.4f);
	}
	ImGui::EndMainMenuBar();

	if (_show_world_inspector)
	{
		ImGui::Begin("World Inspector");
		_world->Inspect();
		ImGui::End();
	}

	if(_show_profiler)
	{
		_profiler->Inspect();
	}

	if (_show_imgui_test)
	{
		ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
		ImGui::ShowTestWindow(&_show_imgui_test);
	}

	if(_show_engine_compoents)
	{
		ImGui::Begin("Engine Inspector");
		for (auto& c : _components)
		{
			string name = typeid(*c).name();
			name = StringReplace(name, "class ", "");
			if (ImGui::CollapsingHeader(name.c_str()))
			{
				c->Inspect();
			}
		}
		ImGui::End();
	}

	if (_show_settings)
	{
		ImGui::Begin("Settings Inspector");
		_settings.Inspect();
		ImGui::End();
	}

	ImGui::Render();
}
#endif

/*
void CEngine::Update()
{
	ASSERT(_initialized);
}

void CEngine::Render()
{
	ASSERT(_initialized);
}
*/<|endoftext|>


<commit_before>#pragma once

#include <array>
#include <memory>
#include <vector>

#include "DataSpec/DNACommon/DNACommon.hpp"

#include "Runtime/CBasics.hpp"
#include "Runtime/CGameOptions.hpp"
#include "Runtime/CPlayerState.hpp"
#include "Runtime/CRelayTracker.hpp"
#include "Runtime/AutoMapper/CMapWorldInfo.hpp"
#include "Runtime/World/CWorld.hpp"
#include "Runtime/World/CWorldTransManager.hpp"

namespace urde {
class CSaveWorldMemory;

class CWorldLayerState {
  friend class CSaveWorldIntermediate;
  std::vector<CWorldLayers::Area> x0_areaLayers;
  DataSpec::WordBitmap x10_saveLayers;

public:
  CWorldLayerState() = default;
  CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld);

  bool IsLayerActive(int areaIdx, int layerIdx) const { return ((x0_areaLayers[areaIdx].m_layerBits >> layerIdx) & 1); }

  void SetLayerActive(int areaIdx, int layerIdx, bool active) {
    if (active)
      x0_areaLayers[areaIdx].m_layerBits |= uint64_t(1) << layerIdx;
    else
      x0_areaLayers[areaIdx].m_layerBits &= ~(uint64_t(1) << layerIdx);
  }

  void InitializeWorldLayers(const std::vector<CWorldLayers::Area>& layers);

  u32 GetAreaLayerCount(int areaIdx) const { return x0_areaLayers[areaIdx].m_layerCount; }
  u32 GetAreaCount() const { return x0_areaLayers.size(); }

  void PutTo(CBitStreamWriter& writer) const;
};

class CWorldState {
  CAssetId x0_mlvlId;
  TAreaId x4_areaId = kInvalidAreaId;
  std::shared_ptr<CRelayTracker> x8_relayTracker;
  std::shared_ptr<CMapWorldInfo> xc_mapWorldInfo;
  CAssetId x10_desiredAreaAssetId;
  std::shared_ptr<CWorldLayerState> x14_layerState;

public:
  explicit CWorldState(CAssetId id);
  CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld);
  CAssetId GetWorldAssetId() const { return x0_mlvlId; }
  void SetAreaId(TAreaId aid) { x4_areaId = aid; }
  TAreaId GetCurrentAreaId() const { return x4_areaId; }
  CAssetId GetDesiredAreaAssetId() const { return x10_desiredAreaAssetId; }
  void SetDesiredAreaAssetId(CAssetId id) { x10_desiredAreaAssetId = id; }
  const std::shared_ptr<CRelayTracker>& RelayTracker() const { return x8_relayTracker; }
  const std::shared_ptr<CMapWorldInfo>& MapWorldInfo() const { return xc_mapWorldInfo; }
  const std::shared_ptr<CWorldLayerState>& GetLayerState() const { return x14_layerState; }
  void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const;
};

class CGameState {
  friend class CStateManager;

  std::array<bool, 128> x0_{};
  u32 x80_;
  CAssetId x84_mlvlId;
  std::vector<CWorldState> x88_worldStates;
  std::shared_ptr<CPlayerState> x98_playerState;
  std::shared_ptr<CWorldTransManager> x9c_transManager;
  double xa0_playTime = 0.0;
  CPersistentOptions xa8_systemOptions;
  CGameOptions x17c_gameOptions;
  CHintOptions x1f8_hintOptions;
  u32 x20c_saveFileIdx = 0;
  u64 x210_cardSerial = 0;
  std::vector<u8> x218_backupBuf;
  bool x228_24_hardMode : 1;
  bool x228_25_initPowerupsAtFirstSpawn : 1;

public:
  CGameState();
  CGameState(CBitStreamReader& stream, u32 saveIdx);
  void SetCurrentWorldId(CAssetId id);
  std::shared_ptr<CPlayerState> GetPlayerState() const { return x98_playerState; }
  std::shared_ptr<CWorldTransManager> GetWorldTransitionManager() const { return x9c_transManager; }
  void SetTotalPlayTime(double time);
  double GetTotalPlayTime() const { return xa0_playTime; }
  CPersistentOptions& SystemOptions() { return xa8_systemOptions; }
  CGameOptions& GameOptions() { return x17c_gameOptions; }
  CHintOptions& HintOptions() { return x1f8_hintOptions; }
  CWorldState& StateForWorld(CAssetId mlvlId);
  CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); }
  CAssetId CurrentWorldAssetId() const { return x84_mlvlId; }
  void SetHardMode(bool v) { x228_24_hardMode = v; }
  bool GetHardMode() const { return x228_24_hardMode; }
  void ReadPersistentOptions(CBitStreamReader& r);
  void SetPersistentOptions(const CPersistentOptions& opts) { xa8_systemOptions = opts; }
  void ImportPersistentOptions(const CPersistentOptions& opts);
  void ExportPersistentOptions(CPersistentOptions& opts) const;
  void SetGameOptions(const CGameOptions& opts) { x17c_gameOptions = opts; }
  void WriteBackupBuf();
  std::vector<u8>& BackupBuf() { return x218_backupBuf; }
  u32 GetFileIdx() const { return x20c_saveFileIdx; }
  void SetFileIdx(u32 idx) { x20c_saveFileIdx = idx; }
  void SetCardSerial(u64 serial) { x210_cardSerial = serial; }
  u64 GetCardSerial() const { return x210_cardSerial; }
  void PutTo(CBitStreamWriter& writer);
  float GetHardModeDamageMultiplier() const;
  float GetHardModeWeaponMultiplier() const;
  void InitializeMemoryWorlds();
  void InitializeMemoryStates();

  struct GameFileStateInfo {
    double x0_playTime;
    CAssetId x8_mlvlId;
    float xc_health;
    u32 x10_energyTanks;
    u32 x14_timestamp;
    u32 x18_itemPercent;
    float x1c_scanPercent;
    bool x20_hardMode;
  };
  static GameFileStateInfo LoadGameFileState(const u8* data);
};
} // namespace urde
<commit_msg>CGameState: Always initialize x80_<commit_after>#pragma once

#include <array>
#include <memory>
#include <vector>

#include "DataSpec/DNACommon/DNACommon.hpp"

#include "Runtime/CBasics.hpp"
#include "Runtime/CGameOptions.hpp"
#include "Runtime/CPlayerState.hpp"
#include "Runtime/CRelayTracker.hpp"
#include "Runtime/AutoMapper/CMapWorldInfo.hpp"
#include "Runtime/World/CWorld.hpp"
#include "Runtime/World/CWorldTransManager.hpp"

namespace urde {
class CSaveWorldMemory;

class CWorldLayerState {
  friend class CSaveWorldIntermediate;
  std::vector<CWorldLayers::Area> x0_areaLayers;
  DataSpec::WordBitmap x10_saveLayers;

public:
  CWorldLayerState() = default;
  CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld);

  bool IsLayerActive(int areaIdx, int layerIdx) const { return ((x0_areaLayers[areaIdx].m_layerBits >> layerIdx) & 1); }

  void SetLayerActive(int areaIdx, int layerIdx, bool active) {
    if (active)
      x0_areaLayers[areaIdx].m_layerBits |= uint64_t(1) << layerIdx;
    else
      x0_areaLayers[areaIdx].m_layerBits &= ~(uint64_t(1) << layerIdx);
  }

  void InitializeWorldLayers(const std::vector<CWorldLayers::Area>& layers);

  u32 GetAreaLayerCount(int areaIdx) const { return x0_areaLayers[areaIdx].m_layerCount; }
  u32 GetAreaCount() const { return x0_areaLayers.size(); }

  void PutTo(CBitStreamWriter& writer) const;
};

class CWorldState {
  CAssetId x0_mlvlId;
  TAreaId x4_areaId = kInvalidAreaId;
  std::shared_ptr<CRelayTracker> x8_relayTracker;
  std::shared_ptr<CMapWorldInfo> xc_mapWorldInfo;
  CAssetId x10_desiredAreaAssetId;
  std::shared_ptr<CWorldLayerState> x14_layerState;

public:
  explicit CWorldState(CAssetId id);
  CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld);
  CAssetId GetWorldAssetId() const { return x0_mlvlId; }
  void SetAreaId(TAreaId aid) { x4_areaId = aid; }
  TAreaId GetCurrentAreaId() const { return x4_areaId; }
  CAssetId GetDesiredAreaAssetId() const { return x10_desiredAreaAssetId; }
  void SetDesiredAreaAssetId(CAssetId id) { x10_desiredAreaAssetId = id; }
  const std::shared_ptr<CRelayTracker>& RelayTracker() const { return x8_relayTracker; }
  const std::shared_ptr<CMapWorldInfo>& MapWorldInfo() const { return xc_mapWorldInfo; }
  const std::shared_ptr<CWorldLayerState>& GetLayerState() const { return x14_layerState; }
  void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const;
};

class CGameState {
  friend class CStateManager;

  std::array<bool, 128> x0_{};
  u32 x80_ = 0;
  CAssetId x84_mlvlId;
  std::vector<CWorldState> x88_worldStates;
  std::shared_ptr<CPlayerState> x98_playerState;
  std::shared_ptr<CWorldTransManager> x9c_transManager;
  double xa0_playTime = 0.0;
  CPersistentOptions xa8_systemOptions;
  CGameOptions x17c_gameOptions;
  CHintOptions x1f8_hintOptions;
  u32 x20c_saveFileIdx = 0;
  u64 x210_cardSerial = 0;
  std::vector<u8> x218_backupBuf;
  bool x228_24_hardMode : 1;
  bool x228_25_initPowerupsAtFirstSpawn : 1;

public:
  CGameState();
  CGameState(CBitStreamReader& stream, u32 saveIdx);
  void SetCurrentWorldId(CAssetId id);
  std::shared_ptr<CPlayerState> GetPlayerState() const { return x98_playerState; }
  std::shared_ptr<CWorldTransManager> GetWorldTransitionManager() const { return x9c_transManager; }
  void SetTotalPlayTime(double time);
  double GetTotalPlayTime() const { return xa0_playTime; }
  CPersistentOptions& SystemOptions() { return xa8_systemOptions; }
  CGameOptions& GameOptions() { return x17c_gameOptions; }
  CHintOptions& HintOptions() { return x1f8_hintOptions; }
  CWorldState& StateForWorld(CAssetId mlvlId);
  CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); }
  CAssetId CurrentWorldAssetId() const { return x84_mlvlId; }
  void SetHardMode(bool v) { x228_24_hardMode = v; }
  bool GetHardMode() const { return x228_24_hardMode; }
  void ReadPersistentOptions(CBitStreamReader& r);
  void SetPersistentOptions(const CPersistentOptions& opts) { xa8_systemOptions = opts; }
  void ImportPersistentOptions(const CPersistentOptions& opts);
  void ExportPersistentOptions(CPersistentOptions& opts) const;
  void SetGameOptions(const CGameOptions& opts) { x17c_gameOptions = opts; }
  void WriteBackupBuf();
  std::vector<u8>& BackupBuf() { return x218_backupBuf; }
  u32 GetFileIdx() const { return x20c_saveFileIdx; }
  void SetFileIdx(u32 idx) { x20c_saveFileIdx = idx; }
  void SetCardSerial(u64 serial) { x210_cardSerial = serial; }
  u64 GetCardSerial() const { return x210_cardSerial; }
  void PutTo(CBitStreamWriter& writer);
  float GetHardModeDamageMultiplier() const;
  float GetHardModeWeaponMultiplier() const;
  void InitializeMemoryWorlds();
  void InitializeMemoryStates();

  struct GameFileStateInfo {
    double x0_playTime;
    CAssetId x8_mlvlId;
    float xc_health;
    u32 x10_energyTanks;
    u32 x14_timestamp;
    u32 x18_itemPercent;
    float x1c_scanPercent;
    bool x20_hardMode;
  };
  static GameFileStateInfo LoadGameFileState(const u8* data);
};
} // namespace urde
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

// The computeRoots function included in this is based on materials
// covered by the following copyright and license:
//
// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots(const Matrix& m, Roots& roots)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar s_inv3 = 1.0/3.0;
  const Scalar s_sqrt3 = internal::sqrt(Scalar(3.0));

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(0,1)*m(0,2)*m(1,2) - m(0,0)*m(1,2)*m(1,2) - m(1,1)*m(0,2)*m(0,2) - m(2,2)*m(0,1)*m(0,1);
  Scalar c1 = m(0,0)*m(1,1) - m(0,1)*m(0,1) + m(0,0)*m(2,2) - m(0,2)*m(0,2) + m(1,1)*m(2,2) - m(1,2)*m(1,2);
  Scalar c2 = m(0,0) + m(1,1) + m(2,2);

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar c2_over_3 = c2*s_inv3;
  Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
  if (a_over_3 > Scalar(0))
    a_over_3 = Scalar(0);

  Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));

  Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
  if (q > Scalar(0))
    q = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar rho = internal::sqrt(-a_over_3);
  Scalar theta = std::atan2(internal::sqrt(-q),half_b)*s_inv3;
  Scalar cos_theta = internal::cos(theta);
  Scalar sin_theta = internal::sin(theta);
  roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
  roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
  roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);

  // Sort in increasing order.
  if (roots(0) >= roots(1))
    std::swap(roots(0),roots(1));
  if (roots(1) >= roots(2))
  {
    std::swap(roots(1),roots(2));
    if (roots(0) >= roots(1))
      std::swap(roots(0),roots(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
  // Scale the matrix so its entries are in [-1,1].  The scaling is applied
  // only when at least one matrix entry has magnitude larger than 1.

  Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
  scale = std::max(scale,Scalar(1));
  Matrix scaledMat = mat / scale;

  // Compute the eigenvalues
//   scaledMat.setZero();
  computeRoots(scaledMat,evals);

  // compute the eigen vectors
  // **here we assume 3 differents eigenvalues**

  // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

  // naive version
  Matrix tmp;
  tmp = scaledMat;
  tmp.diagonal().array() -= evals(0);
  evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(1);
  evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(2);
  evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

  // Rescale back to the original size.
  evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<commit_msg>slightly more stable eigen vector computation<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

// The computeRoots function included in this is based on materials
// covered by the following copyright and license:
//
// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots(const Matrix& m, Roots& roots)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar s_inv3 = 1.0/3.0;
  const Scalar s_sqrt3 = internal::sqrt(Scalar(3.0));

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(0,1)*m(0,2)*m(1,2) - m(0,0)*m(1,2)*m(1,2) - m(1,1)*m(0,2)*m(0,2) - m(2,2)*m(0,1)*m(0,1);
  Scalar c1 = m(0,0)*m(1,1) - m(0,1)*m(0,1) + m(0,0)*m(2,2) - m(0,2)*m(0,2) + m(1,1)*m(2,2) - m(1,2)*m(1,2);
  Scalar c2 = m(0,0) + m(1,1) + m(2,2);

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar c2_over_3 = c2*s_inv3;
  Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
  if (a_over_3 > Scalar(0))
    a_over_3 = Scalar(0);

  Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));

  Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
  if (q > Scalar(0))
    q = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar rho = internal::sqrt(-a_over_3);
  Scalar theta = std::atan2(internal::sqrt(-q),half_b)*s_inv3;
  Scalar cos_theta = internal::cos(theta);
  Scalar sin_theta = internal::sin(theta);
  roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
  roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
  roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);

  // Sort in increasing order.
  if (roots(0) >= roots(1))
    std::swap(roots(0),roots(1));
  if (roots(1) >= roots(2))
  {
    std::swap(roots(1),roots(2));
    if (roots(0) >= roots(1))
      std::swap(roots(0),roots(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
  // Scale the matrix so its entries are in [-1,1].  The scaling is applied
  // only when at least one matrix entry has magnitude larger than 1.

  Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
  scale = std::max(scale,Scalar(1));
  Matrix scaledMat = mat / scale;

  // Compute the eigenvalues
//   scaledMat.setZero();
  computeRoots(scaledMat,evals);

  // compute the eigen vectors
  // **here we assume 3 differents eigenvalues**

  // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

//   // naive version
//   Matrix tmp;
//   tmp = scaledMat;
//   tmp.diagonal().array() -= evals(0);
//   evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();
//
//   tmp = scaledMat;
//   tmp.diagonal().array() -= evals(1);
//   evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();
//
//   tmp = scaledMat;
//   tmp.diagonal().array() -= evals(2);
//   evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

  // a slighlty more stable version:
  Matrix tmp;
  tmp = scaledMat;
  tmp.diagonal ().array () -= evals (2);
  evecs.col (2) = tmp.row (0).cross (tmp.row (1)).normalized ();
  tmp = scaledMat;
  tmp.diagonal ().array () -= evals (1);
  evecs.col(1) = tmp.row (0).cross(tmp.row (1));
  Scalar n1 = evecs.col(1).norm();
  if(n1<=Eigen::NumTraits<Scalar>::epsilon())
    evecs.col(1) = evecs.col(2).unitOrthogonal();
  else
    evecs.col(1) /= n1;
  evecs.col(0) = evecs.col(2).cross(evecs.col(1));

  // Rescale back to the original size.
  evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<|endoftext|>


<commit_before>#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots (const Matrix& rkA, Roots& adRoot)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar msInv3 = 1.0/3.0;
  const Scalar msRoot3 = ei_sqrt(Scalar(3.0));

  Scalar dA00 = rkA(0,0);
  Scalar dA01 = rkA(0,1);
  Scalar dA02 = rkA(0,2);
  Scalar dA11 = rkA(1,1);
  Scalar dA12 = rkA(1,2);
  Scalar dA22 = rkA(2,2);

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar dC0 = dA00*dA11*dA22 + Scalar(2)*dA01*dA02*dA12 - dA00*dA12*dA12 - dA11*dA02*dA02 - dA22*dA01*dA01;
  Scalar dC1 = dA00*dA11 - dA01*dA01 + dA00*dA22 - dA02*dA02 + dA11*dA22 - dA12*dA12;
  Scalar dC2 = dA00 + dA11 + dA22;

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar dC2Div3 = dC2*msInv3;
  Scalar dADiv3 = (dC1 - dC2*dC2Div3)*msInv3;
  if (dADiv3 > Scalar(0))
    dADiv3 = Scalar(0);

  Scalar dMBDiv2 = Scalar(0.5)*(dC0 + dC2Div3*(Scalar(2)*dC2Div3*dC2Div3 - dC1));

  Scalar dQ = dMBDiv2*dMBDiv2 + dADiv3*dADiv3*dADiv3;
  if (dQ > Scalar(0))
    dQ = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar dMagnitude = ei_sqrt(-dADiv3);
  Scalar dAngle = std::atan2(ei_sqrt(-dQ),dMBDiv2)*msInv3;
  Scalar dCos = ei_cos(dAngle);
  Scalar dSin = ei_sin(dAngle);
  adRoot(0) = dC2Div3 + 2.f*dMagnitude*dCos;
  adRoot(1) = dC2Div3 - dMagnitude*(dCos + msRoot3*dSin);
  adRoot(2) = dC2Div3 - dMagnitude*(dCos - msRoot3*dSin);

  // Sort in increasing order.
  if (adRoot(0) >= adRoot(1))
    std::swap(adRoot(0),adRoot(1));
  if (adRoot(1) >= adRoot(2))
  {
    std::swap(adRoot(1),adRoot(2));
    if (adRoot(0) >= adRoot(1))
      std::swap(adRoot(0),adRoot(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
    // Scale the matrix so its entries are in [-1,1].  The scaling is applied
    // only when at least one matrix entry has magnitude larger than 1.

    Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
    scale = std::max(scale,Scalar(1));
    Matrix scaledMat = mat / scale;

    // Compute the eigenvalues
//     scaledMat.setZero();
    computeRoots(scaledMat,evals);

    // compute the eigen vectors
    // here we assume 3 differents eigenvalues

    // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

    // naive version
    Matrix tmp;
    tmp = scaledMat;
    tmp.diagonal().array() -= evals(0);
    evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();

    tmp = scaledMat;
    tmp.diagonal().array() -= evals(1);
    evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();

    tmp = scaledMat;
    tmp.diagonal().array() -= evals(2);
    evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

    // Rescale back to the original size.
    evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<commit_msg>add missing copyrights<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

// The computeRoots function included in this is based on materials
// covered by the following copyright and license:
//
// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots(const Matrix& m, Roots& roots)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar s_inv3 = 1.0/3.0;
  const Scalar s_sqrt3 = ei_sqrt(Scalar(3.0));

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(0,1)*m(0,2)*m(1,2) - m(0,0)*m(1,2)*m(1,2) - m(1,1)*m(0,2)*m(0,2) - m(2,2)*m(0,1)*m(0,1);
  Scalar c1 = m(0,0)*m(1,1) - m(0,1)*m(0,1) + m(0,0)*m(2,2) - m(0,2)*m(0,2) + m(1,1)*m(2,2) - m(1,2)*m(1,2);
  Scalar c2 = m(0,0) + m(1,1) + m(2,2);

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar c2_over_3 = c2*s_inv3;
  Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
  if (a_over_3 > Scalar(0))
    a_over_3 = Scalar(0);

  Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));

  Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
  if (q > Scalar(0))
    q = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar rho = ei_sqrt(-a_over_3);
  Scalar theta = std::atan2(ei_sqrt(-q),half_b)*s_inv3;
  Scalar cos_theta = ei_cos(theta);
  Scalar sin_theta = ei_sin(theta);
  roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
  roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
  roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);

  // Sort in increasing order.
  if (roots(0) >= roots(1))
    std::swap(roots(0),roots(1));
  if (roots(1) >= roots(2))
  {
    std::swap(roots(1),roots(2));
    if (roots(0) >= roots(1))
      std::swap(roots(0),roots(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
  // Scale the matrix so its entries are in [-1,1].  The scaling is applied
  // only when at least one matrix entry has magnitude larger than 1.

  Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
  scale = std::max(scale,Scalar(1));
  Matrix scaledMat = mat / scale;

  // Compute the eigenvalues
//   scaledMat.setZero();
  computeRoots(scaledMat,evals);

  // compute the eigen vectors
  // **here we assume 3 differents eigenvalues**

  // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

  // naive version
  Matrix tmp;
  tmp = scaledMat;
  tmp.diagonal().array() -= evals(0);
  evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(1);
  evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(2);
  evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

  // Rescale back to the original size.
  evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<|endoftext|>


<commit_before>//
//  segmentationManager.cpp
//  noteSegmentation
//
//  Created by zach on 1/17/14.
//
//

#include "segmentationManager.h"

void segmentationManager::setup( int numPitchDetectors, int bufferSize ){

    int nPds = numPitchDetectors;
    smoother tempSmoother;
    tempSmoother.setNumPValues(11);
    for (int i = 0; i < nPds; i++) {
        smoothers.push_back(tempSmoother);
    }

    graphWidth = ofGetWidth()/2;
    graphHeight = ofGetHeight()/3;
    graphMax = 120;

    scrollingGraph tempGraph;
    tempGraph.setup(graphWidth, 0, 0, graphMax);
    for (int i = 0; i < nPds; i++) {
        pitchGraphs.push_back(tempGraph);
        medianGraphs.push_back(tempGraph);
        velGraphs.push_back(tempGraph);
    }

    for (int i = 0; i < nPds; i++) {
        ofColor tempColor;
        tempColor.setHsb(i*40, 255, 180, 200);
        graphColors.push_back(tempColor);
    }

    runs.setup(graphWidth, 0, 0, 1);

    coarseThreshold = fineThreshold = 1.0;

    minDuration = 25;
    maxDuration = 50;
    drawMarkers = true;
    bAmRecording = false;
    minPitch = 20;

    //segment playback
    sinAngle = 0;
    audioVol = 1.0;
    sinVol = 0.0;
    samplerOctavesUp = sinOctavesUp = 0;
}

void segmentationManager::update(float * samples){

    for (int i = 0; i < PDM->size(); i++) {
        pitchGraphs[i].addValue(PDM->getPitch(i));
        smoothers[i].addValue(PDM->getPitch(i));
        medianGraphs[i].addValue(smoothers[i].getMedian());

        float lastVal = medianGraphs[i].valHistory[medianGraphs[i].valHistory.size() - 1];
        float secondLastVal = medianGraphs[i].valHistory[medianGraphs[i].valHistory.size() - 2];
        float vel = abs(lastVal - secondLastVal);
        velGraphs[i].addValue(vel);
    }

    // count how many frames in a row the vel is below the threshold
    if ( velGraphs[PDM->PDMethod].getLast() < (bVelFine ? fineThreshold : coarseThreshold)) {
        //count buffers
        noteRun++;
//        bAmRecording = true;
        // record samples
        for (int i = 0; i < bufferSize; i++ ) {
            currentNote.samples.push_back(samples[i]);
        }
        //record pitches
//        pitchesForRecording.push_back(medianGraphs[PDM->PDMethod].getLast());
        currentNote.analysisFrames.push_back(medianGraphs[PDM->PDMethod].getLast());

    }
    else  {
        // if the vel is above the thresh then check if the current run is longer than the min duration. If so save the note.  Regardless, set the run count to zero.

//        bAmRecording = false;

        if ( noteRun > minDuration) {

            marker segment;
            segment.start = graphWidth - 1 - noteRun;
            segment.end = graphWidth - 1;

            float avg = 0;
            for (int i = 0; i < currentNote.analysisFrames.size(); i++){
                avg += currentNote.analysisFrames[i];
            }
            avg /= (MAX(1.0, currentNote.analysisFrames.size()));

//            pitchesForRecording.clear();
            // zero periods look like 9, 10... etc...
            if (avg > minPitch){
                //add markers
                markers.push_back(segment);
                //add correspnding note
                currentNote.playhead = 0;
                currentNote.bPlaying = true;
                currentNote.bWasPlaying = false;
                currentNote.mostCommonPitch = findMostCommonPitch(currentNote);
                notes.push_back(currentNote);
            }
            //            cout << "note recorded - min duration = " << minDuration << endl << endl;
        }
        //reset
        noteRun = 0;
        currentNote.samples.clear();
        currentNote.analysisFrames.clear();
    }

    //    cout << noteRun << " " << bAmRecording << " vel = " << velGraphs[PDMethod].getLast() << " thresh = " << threshold << endl;

    runs.addValue(bAmRecording);

    //    scroll markers
    if (markers.size() > 0) {
        for (int i = 0; i < markers.size(); i++) {
            markers[i].start--;
            markers[i].end--;
        }
    }
}

void segmentationManager::draw(){

    ofSetColor(25);
    ofLine(ofGetWidth() - minDuration * 2, 90, ofGetWidth(), 90);
    ofLine(ofGetWidth() - minDuration * 2, 92, ofGetWidth() - minDuration * 2, 88);

    (noteRun < minDuration) ? ofSetColor(255,0,0) : ofSetColor(0,255,0);
    ofLine(ofGetWidth() - noteRun * 2, 95, ofGetWidth(), 95);

    ofPushMatrix();
    ofTranslate(0, 100);
    ofSetColor(255, 10, 10);
    medianGraphs[ PDM->getMethod() ].draw(graphHeight);
    //        ofSetColor(25);
    //        runs.draw(graphHeight);

    if (drawMarkers) {

        for (int i = 0; i < markers.size(); i++) {
            ofSetColor(255,255,255,127);
            ofRect(markers[i].start * 2, 0, markers[i].end * 2 - markers[i].start * 2, graphHeight);
        }
    }
    ofPopMatrix();

    ofPushMatrix();
    ofTranslate(0, graphHeight + 100);
    ofSetColor(255,0,0);

    if (bVelFine) {
        velGraphs[ PDM->getMethod() ].draw(graphHeight, 0.0, 2.0);
    }
    else {
        velGraphs[ PDM->getMethod() ].draw(graphHeight);
    }

    if (drawMarkers) {

        ofSetColor(0);
        float threshLineHeight = graphHeight - ((bVelFine ? fineThreshold/2*graphMax : coarseThreshold ) / graphMax * graphHeight);
        ofLine(0, threshLineHeight, ofGetWidth(), threshLineHeight);

        ofSetColor(0,0,0,127);
        for (int j = 0; j < velGraphs[ PDM->getMethod() ].valHistory.size(); j++) {
            if ( velGraphs[ PDM->getMethod() ].valHistory[j] > (bVelFine ? fineThreshold : coarseThreshold ) ) {
                ofLine(j * 2, -graphHeight, j * 2, graphHeight);
            }
        }

    }

    ofPopMatrix();

}

void segmentationManager::playSegments(vector<float> &output){
//    vector<float> output;
//    output.assign(bufferSize, 0.0);

    for (int i = 0; i < notes.size(); i++){

        //play sampler
        if ( !notes[i].bWasPlaying && notes[i].bPlaying ) {
            AU->startNote(notes[i].mostCommonPitch + samplerOctavesUp * 12);
        }
        else if ( notes[i].bWasPlaying && !notes[i].bPlaying ) {
            AU->stopNote(notes[i].mostCommonPitch + samplerOctavesUp * 12);
        }

        notes[i].bWasPlaying = notes[i].bPlaying;

        //clear buffer
//        for (int j = 0; j < bufferSize; j++){
//            output[j] = 0;
//        }

        //while audio clips are not finshed playing
        if (notes[i].bPlaying == true && (notes[i].playhead + bufferSize) < notes[i].samples.size()){
            //play audio
            int playhead = notes[i].playhead;
            for (int j = 0; j < bufferSize; j++){
                output[j] += notes[i].samples[playhead + j] * 0.2 * audioVol;
            }
            notes[i].playhead += bufferSize ;

            //play sine wave
            int frame = playhead / bufferSize;
            int midiNote = notes[i].analysisFrames[frame];

            float freq = pow(2, float(midiNote-69)/12.0)*440;
            freq *= pow(2.0, sinOctavesUp);
            //            cout << frame << " / " << notes[i].analysisFrames.size() << " midi " << midiNote << " freq " << freq << endl;
            //fm  =  2(m−69)/12(440 Hz)
            float sinAngleAdder = freq * TWO_PI / 44100.0;

            for (int j = 0; j < bufferSize; j++){

                output[j] += sin(sinAngle) * 0.2 * sinVol;

                sinAngle+= sinAngleAdder;

            }

            while (sinAngle > PI) sinAngle -= TWO_PI;

        } else {
            notes[i].bPlaying = false;
        }

    }

}

float segmentationManager::findMostCommonPitch(audioNote note){

    vector < int > notes;
    for (int i = 0; i < note.analysisFrames.size(); i++){
        float freq = note.analysisFrames[i];

        if (freq > 0){
            int note = freq;
            if (note > 0 && note < 150) notes.push_back(note);
        }
    }

    // see utils.h

    return findMostCommon(notes);

}
<commit_msg>refactored findMostCommonPitch with better var names and got rid of redundant logic<commit_after>//
//  segmentationManager.cpp
//  noteSegmentation
//
//  Created by zach on 1/17/14.
//
//

#include "segmentationManager.h"

void segmentationManager::setup( int numPitchDetectors, int bufferSize ){

    int nPds = numPitchDetectors;
    smoother tempSmoother;
    tempSmoother.setNumPValues(11);
    for (int i = 0; i < nPds; i++) {
        smoothers.push_back(tempSmoother);
    }

    graphWidth = ofGetWidth()/2;
    graphHeight = ofGetHeight()/3;
    graphMax = 120;

    scrollingGraph tempGraph;
    tempGraph.setup(graphWidth, 0, 0, graphMax);
    for (int i = 0; i < nPds; i++) {
        pitchGraphs.push_back(tempGraph);
        medianGraphs.push_back(tempGraph);
        velGraphs.push_back(tempGraph);
    }

    for (int i = 0; i < nPds; i++) {
        ofColor tempColor;
        tempColor.setHsb(i*40, 255, 180, 200);
        graphColors.push_back(tempColor);
    }

    runs.setup(graphWidth, 0, 0, 1);

    coarseThreshold = fineThreshold = 1.0;

    minDuration = 25;
    maxDuration = 50;
    drawMarkers = true;
    bAmRecording = false;
    minPitch = 20;

    //segment playback
    sinAngle = 0;
    audioVol = 1.0;
    sinVol = 0.0;
    samplerOctavesUp = sinOctavesUp = 0;
}

void segmentationManager::update(float * samples){

    for (int i = 0; i < PDM->size(); i++) {
        pitchGraphs[i].addValue(PDM->getPitch(i));
        smoothers[i].addValue(PDM->getPitch(i));
        medianGraphs[i].addValue(smoothers[i].getMedian());

        float lastVal = medianGraphs[i].valHistory[medianGraphs[i].valHistory.size() - 1];
        float secondLastVal = medianGraphs[i].valHistory[medianGraphs[i].valHistory.size() - 2];
        float vel = abs(lastVal - secondLastVal);
        velGraphs[i].addValue(vel);
    }

    // count how many frames in a row the vel is below the threshold
    if ( velGraphs[PDM->PDMethod].getLast() < (bVelFine ? fineThreshold : coarseThreshold)) {
        //count buffers
        noteRun++;
//        bAmRecording = true;
        // record samples
        for (int i = 0; i < bufferSize; i++ ) {
            currentNote.samples.push_back(samples[i]);
        }
        //record pitches
//        pitchesForRecording.push_back(medianGraphs[PDM->PDMethod].getLast());
        currentNote.analysisFrames.push_back(medianGraphs[PDM->PDMethod].getLast());

    }
    else  {
        // if the vel is above the thresh then check if the current run is longer than the min duration. If so save the note.  Regardless, set the run count to zero.

//        bAmRecording = false;

        if ( noteRun > minDuration) {

            marker segment;
            segment.start = graphWidth - 1 - noteRun;
            segment.end = graphWidth - 1;

            float avg = 0;
            for (int i = 0; i < currentNote.analysisFrames.size(); i++){
                avg += currentNote.analysisFrames[i];
            }
            avg /= (MAX(1.0, currentNote.analysisFrames.size()));

//            pitchesForRecording.clear();
            // zero periods look like 9, 10... etc...
            if (avg > minPitch){
                //add markers
                markers.push_back(segment);
                //add correspnding note
                currentNote.playhead = 0;
                currentNote.bPlaying = true;
                currentNote.bWasPlaying = false;
                currentNote.mostCommonPitch = findMostCommonPitch(currentNote);
                notes.push_back(currentNote);
            }
            //            cout << "note recorded - min duration = " << minDuration << endl << endl;
        }
        //reset
        noteRun = 0;
        currentNote.samples.clear();
        currentNote.analysisFrames.clear();
    }

    //    cout << noteRun << " " << bAmRecording << " vel = " << velGraphs[PDMethod].getLast() << " thresh = " << threshold << endl;

    runs.addValue(bAmRecording);

    //    scroll markers
    if (markers.size() > 0) {
        for (int i = 0; i < markers.size(); i++) {
            markers[i].start--;
            markers[i].end--;
        }
    }
}

void segmentationManager::draw(){

    ofSetColor(25);
    ofLine(ofGetWidth() - minDuration * 2, 90, ofGetWidth(), 90);
    ofLine(ofGetWidth() - minDuration * 2, 92, ofGetWidth() - minDuration * 2, 88);

    (noteRun < minDuration) ? ofSetColor(255,0,0) : ofSetColor(0,255,0);
    ofLine(ofGetWidth() - noteRun * 2, 95, ofGetWidth(), 95);

    ofPushMatrix();
    ofTranslate(0, 100);
    ofSetColor(255, 10, 10);
    medianGraphs[ PDM->getMethod() ].draw(graphHeight);
    //        ofSetColor(25);
    //        runs.draw(graphHeight);

    if (drawMarkers) {

        for (int i = 0; i < markers.size(); i++) {
            ofSetColor(255,255,255,127);
            ofRect(markers[i].start * 2, 0, markers[i].end * 2 - markers[i].start * 2, graphHeight);
        }
    }
    ofPopMatrix();

    ofPushMatrix();
    ofTranslate(0, graphHeight + 100);
    ofSetColor(255,0,0);

    if (bVelFine) {
        velGraphs[ PDM->getMethod() ].draw(graphHeight, 0.0, 2.0);
    }
    else {
        velGraphs[ PDM->getMethod() ].draw(graphHeight);
    }

    if (drawMarkers) {

        ofSetColor(0);
        float threshLineHeight = graphHeight - ((bVelFine ? fineThreshold/2*graphMax : coarseThreshold ) / graphMax * graphHeight);
        ofLine(0, threshLineHeight, ofGetWidth(), threshLineHeight);

        ofSetColor(0,0,0,127);
        for (int j = 0; j < velGraphs[ PDM->getMethod() ].valHistory.size(); j++) {
            if ( velGraphs[ PDM->getMethod() ].valHistory[j] > (bVelFine ? fineThreshold : coarseThreshold ) ) {
                ofLine(j * 2, -graphHeight, j * 2, graphHeight);
            }
        }

    }

    ofPopMatrix();

}

void segmentationManager::playSegments(vector<float> &output){
//    vector<float> output;
//    output.assign(bufferSize, 0.0);

    for (int i = 0; i < notes.size(); i++){

        //play sampler
        if ( !notes[i].bWasPlaying && notes[i].bPlaying ) {
            AU->startNote(notes[i].mostCommonPitch + samplerOctavesUp * 12);
        }
        else if ( notes[i].bWasPlaying && !notes[i].bPlaying ) {
            AU->stopNote(notes[i].mostCommonPitch + samplerOctavesUp * 12);
        }

        notes[i].bWasPlaying = notes[i].bPlaying;

        //clear buffer
//        for (int j = 0; j < bufferSize; j++){
//            output[j] = 0;
//        }

        //while audio clips are not finshed playing
        if (notes[i].bPlaying == true && (notes[i].playhead + bufferSize) < notes[i].samples.size()){
            //play audio
            int playhead = notes[i].playhead;
            for (int j = 0; j < bufferSize; j++){
                output[j] += notes[i].samples[playhead + j] * 0.2 * audioVol;
            }
            notes[i].playhead += bufferSize ;

            //play sine wave
            int frame = playhead / bufferSize;
            int midiNote = notes[i].analysisFrames[frame];

            float freq = pow(2, float(midiNote-69)/12.0)*440;
            freq *= pow(2.0, sinOctavesUp);
            //            cout << frame << " / " << notes[i].analysisFrames.size() << " midi " << midiNote << " freq " << freq << endl;
            //fm  =  2(m−69)/12(440 Hz)
            float sinAngleAdder = freq * TWO_PI / 44100.0;

            for (int j = 0; j < bufferSize; j++){

                output[j] += sin(sinAngle) * 0.2 * sinVol;

                sinAngle+= sinAngleAdder;

            }

            while (sinAngle > PI) sinAngle -= TWO_PI;

        } else {
            notes[i].bPlaying = false;
        }

    }

}

float segmentationManager::findMostCommonPitch(audioNote note){

    vector < int > properPitches;

    for (int i = 0; i < note.analysisFrames.size(); i++){
        float detectedPitch = note.analysisFrames[i];
        if (detectedPitch > 0 && detectedPitch < 150) properPitches.push_back(detectedPitch);
    }
    // see utils.h

    return findMostCommon(properPitches);

}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2005 by Christopher Nelson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "manager.h"
#include "frame.h"

#include "csutil/csevent.h"
#include "iengine/engine.h"
#include "iutil/comp.h"
#include "iutil/event.h"
#include "iutil/eventh.h"
#include "iutil/eventq.h"
#include "iutil/objreg.h"
#include "iutil/plugin.h"
#include "iutil/virtclk.h"
#include "ivaria/reporter.h"
#include "ivideo/txtmgr.h"

SCF_IMPLEMENT_FACTORY(awsManager)

SCF_IMPLEMENT_IBASE(awsManager)
  SCF_IMPLEMENTS_INTERFACE(iAws)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE(iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE(awsManager::eiComponent)
  SCF_IMPLEMENTS_INTERFACE(iComponent)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

awsManager::awsManager(iBase *the_base)
{
  SCF_CONSTRUCT_IBASE (the_base);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);
  scfiEventHandler = 0;
}

awsManager::~awsManager()
{
  if (scfiEventHandler)
  {
    csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
    if (q)
      q->RemoveListener (scfiEventHandler);

    scfiEventHandler->DecRef ();
  }

  SCF_DESTRUCT_EMBEDDED_IBASE (scfiComponent);
  SCF_DESTRUCT_IBASE ();
}

bool
awsManager::Initialize (iObjectRegistry *_object_reg)
{
  object_reg = _object_reg;

  return true;
}

void
awsManager::SetDrawTarget(iGraphics2D *_g2d, iGraphics3D *_g3d)
{
  g2d = _g2d;
  g3d = _g3d;

  default_font = g2d->GetFontServer()->LoadFont (CSFONT_LARGE);
}

/*********************************************************************
 ***************** Event Handling ************************************
 ********************************************************************/

bool awsManager::HandleEvent (iEvent &Event)
{
  // Find out what kind of event it is
  switch (Event.Type)
  {
  case csevMouseMove:
  case csevMouseUp:
  case csevMouseClick:
  case csevMouseDown:
  case csevKeyboard:
  case csevBroadcast:
    break;
  }

  return false;
}

/*********************************************************************
 ***************** Redrawing *****************************************
 ********************************************************************/

void awsManager::Redraw()
{
  csPen pen(g2d, g3d);
  //csReversibleTransform rt;
  //rt.Identity();
  //g3d->SetWorldToCamera(rt);

  g2d->Write(default_font, 90, 90, g2d->FindRGB(128,128,128,128), -1, "AWS Redrawing");

  pen.SetColor(0,0,0,1);

  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_CENTER, CS_PEN_TA_CENTER, "Test Boxed Text - Centered");
  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_RIGHT, CS_PEN_TA_TOP, "Test Boxed Text - Right, Top");
  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_LEFT, CS_PEN_TA_BOT, "Test Boxed Text - Left, Bot");

  pen.DrawPoint(0,0);
  pen.DrawLine(0,0,500,500);
  pen.DrawRoundedRect(0,0,500,500,0.5,false);

}

/*********************************************************************
 ***************** Definition Files **********************************
 ********************************************************************/

bool awsManager::Load(const scfString &_filename)
{
  return prefs.load(object_reg, _filename);
}
<commit_msg>Some more changes to AWS2 in testing the drawing.<commit_after>/*
    Copyright (C) 2005 by Christopher Nelson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "manager.h"
#include "frame.h"

#include "csutil/csevent.h"
#include "iengine/engine.h"
#include "iutil/comp.h"
#include "iutil/event.h"
#include "iutil/eventh.h"
#include "iutil/eventq.h"
#include "iutil/objreg.h"
#include "iutil/plugin.h"
#include "iutil/virtclk.h"
#include "ivaria/reporter.h"
#include "ivideo/txtmgr.h"

SCF_IMPLEMENT_FACTORY(awsManager)

SCF_IMPLEMENT_IBASE(awsManager)
  SCF_IMPLEMENTS_INTERFACE(iAws)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE(iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE(awsManager::eiComponent)
  SCF_IMPLEMENTS_INTERFACE(iComponent)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

awsManager::awsManager(iBase *the_base)
{
  SCF_CONSTRUCT_IBASE (the_base);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);
  scfiEventHandler = 0;
}

awsManager::~awsManager()
{
  if (scfiEventHandler)
  {
    csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
    if (q)
      q->RemoveListener (scfiEventHandler);

    scfiEventHandler->DecRef ();
  }

  SCF_DESTRUCT_EMBEDDED_IBASE (scfiComponent);
  SCF_DESTRUCT_IBASE ();
}

bool
awsManager::Initialize (iObjectRegistry *_object_reg)
{
  object_reg = _object_reg;

  return true;
}

void
awsManager::SetDrawTarget(iGraphics2D *_g2d, iGraphics3D *_g3d)
{
  g2d = _g2d;
  g3d = _g3d;

  default_font = g2d->GetFontServer()->LoadFont (CSFONT_LARGE);
}

/*********************************************************************
 ***************** Event Handling ************************************
 ********************************************************************/

bool awsManager::HandleEvent (iEvent &Event)
{
  // Find out what kind of event it is
  switch (Event.Type)
  {
  case csevMouseMove:
  case csevMouseUp:
  case csevMouseClick:
  case csevMouseDown:
  case csevKeyboard:
  case csevBroadcast:
    break;
  }

  return false;
}

/*********************************************************************
 ***************** Redrawing *****************************************
 ********************************************************************/

void awsManager::Redraw()
{
  csPen pen(g2d, g3d);
  csReversibleTransform rt;

  rt.Identity();
  g3d->SetWorldToCamera(rt);

  g2d->Write(default_font, 90, 90, g2d->FindRGB(128,128,128,128), -1, "AWS Redrawing");

  pen.SetColor(1,1,1,1);

  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_CENTER, CS_PEN_TA_CENTER, "Test Boxed Text - Centered");
  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_RIGHT, CS_PEN_TA_TOP, "Test Boxed Text - Right, Top");
  pen.WriteBoxed(default_font, 100,100,500,500, CS_PEN_TA_LEFT, CS_PEN_TA_BOT, "Test Boxed Text - Left, Bot");

  pen.DrawPoint(0,0);
  pen.DrawLine(0,0,500,500);
  pen.DrawRect(0,0,500,500);
  pen.DrawRoundedRect(0,0,500,500,0.5,false);

}

/*********************************************************************
 ***************** Definition Files **********************************
 ********************************************************************/

bool awsManager::Load(const scfString &_filename)
{
  return prefs.load(object_reg, _filename);
}
<|endoftext|>


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

#ifndef DUNE_GDT_SPACE_TOOLS_HH
#define DUNE_GDT_SPACE_TOOLS_HH

#include <memory>
#include <type_traits>

#include "interface.hh"

#if HAVE_DUNE_FEM
# include <dune/fem/gridpart/levelgridpart.hh>
# include <dune/fem/gridpart/leafgridpart.hh>
#endif // HAVE_DUNE_FEM

namespace Dune {
namespace GDT {
namespace SpaceTools {

template< class GridType, bool view = true >
struct LeafGridPartView
{
  typedef typename GridType::LeafGridView Type;

  static Type create(GridType& grid)
  {
    return Type(grid.leafGridView());
  }
}; // struct LeafGridPartView< ..., true >

template< class GridType, bool view = true >
struct LevelGridPartView
{
  typedef typename GridType::LevelGridView Type;

  static Type create(GridType& grid, const int level)
  {
    assert(level >= 0);
    assert(level <= grid.maxLevel());
    return Type(grid.levelGridView(level));
  }
}; // struct LevelGridPartView< ..., true >

#if HAVE_DUNE_FEM

template< class GridType >
struct LeafGridPartView< GridType, false >
{
  typedef Dune::Fem::LeafGridPart< GridType > Type;

  static Type create(GridType& grid)
  {
    return Type(grid);
  }
}; // struct LeafGridPartView< ..., false >

template< class GridType >
struct LevelGridPartView< GridType, false >
{
  typedef Dune::Fem::LevelGridPart< GridType > Type;

  static Type create(GridType& grid, const int level)
  {
    assert(level >= 0);
    assert(level <= grid.maxLevel());
    return Type(grid, level);
  }
}; // struct LevelGridPartView< ..., false >

#endif // HAVE_DUNE_FEM

template< class SpaceType >
class GridPartView
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceType::Traits >, SpaceType >::value,
                "SpaceType has to be derived from SpaceInterface!");
  static const bool needs_grid_view = SpaceType::needs_grid_view;
public:
  typedef typename SpaceType::GridViewType::Grid                        GridType;
  typedef typename LeafGridPartView<  GridType, needs_grid_view >::Type LeafGridViewType;
  typedef typename LevelGridPartView< GridType, needs_grid_view >::Type LevelGridViewType;

  static LeafGridViewType create_leaf(GridType& grid)
  {
    return LeafGridPartView< GridType, needs_grid_view >::create(grid);
  }

  static LevelGridViewType create_level(GridType& grid, const int level)
  {
    return LevelGridPartView< GridType, needs_grid_view >::create(grid, level);
  }
}; // struct GridPartView

} // namespace SpaceTools
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACE_TOOLS_HH
<commit_msg>[spaces.tools] add template parameters for SpaceInterface, refs #14<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACE_TOOLS_HH
#define DUNE_GDT_SPACE_TOOLS_HH

#include <memory>
#include <type_traits>

#include "interface.hh"

#if HAVE_DUNE_FEM
# include <dune/fem/gridpart/levelgridpart.hh>
# include <dune/fem/gridpart/leafgridpart.hh>
#endif // HAVE_DUNE_FEM

namespace Dune {
namespace GDT {
namespace SpaceTools {

template< class GridType, bool view = true >
struct LeafGridPartView
{
  typedef typename GridType::LeafGridView Type;

  static Type create(GridType& grid)
  {
    return Type(grid.leafGridView());
  }
}; // struct LeafGridPartView< ..., true >

template< class GridType, bool view = true >
struct LevelGridPartView
{
  typedef typename GridType::LevelGridView Type;

  static Type create(GridType& grid, const int level)
  {
    assert(level >= 0);
    assert(level <= grid.maxLevel());
    return Type(grid.levelGridView(level));
  }
}; // struct LevelGridPartView< ..., true >

#if HAVE_DUNE_FEM

template< class GridType >
struct LeafGridPartView< GridType, false >
{
  typedef Dune::Fem::LeafGridPart< GridType > Type;

  static Type create(GridType& grid)
  {
    return Type(grid);
  }
}; // struct LeafGridPartView< ..., false >

template< class GridType >
struct LevelGridPartView< GridType, false >
{
  typedef Dune::Fem::LevelGridPart< GridType > Type;

  static Type create(GridType& grid, const int level)
  {
    assert(level >= 0);
    assert(level <= grid.maxLevel());
    return Type(grid, level);
  }
}; // struct LevelGridPartView< ..., false >

#endif // HAVE_DUNE_FEM

template< class SpaceType >
class GridPartView
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceType::Traits,
                                                 SpaceType::dimDomain,
                                                 SpaceType::dimRange,
                                                 SpaceType::dimRangeCols >,
                                 SpaceType >::value,
                "SpaceType has to be derived from SpaceInterface!");
  static const bool needs_grid_view = SpaceType::needs_grid_view;
public:
  typedef typename SpaceType::GridViewType::Grid                        GridType;
  typedef typename LeafGridPartView<  GridType, needs_grid_view >::Type LeafGridViewType;
  typedef typename LevelGridPartView< GridType, needs_grid_view >::Type LevelGridViewType;

  static LeafGridViewType create_leaf(GridType& grid)
  {
    return LeafGridPartView< GridType, needs_grid_view >::create(grid);
  }

  static LevelGridViewType create_level(GridType& grid, const int level)
  {
    return LevelGridPartView< GridType, needs_grid_view >::create(grid, level);
  }
}; // struct GridPartView

} // namespace SpaceTools
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACE_TOOLS_HH
<|endoftext|>