<commit_before>// Copyright [2016] <Salomão Rodrigues Jacinto>
#ifndef NO_BINARIO_HPP
#define NO_BINARIO_HPP

#include <cstdlib>
#include <vector>
#include <stdexcept>

/**
 * @brief      Implementação de uma estrutura de Árvore Binária em C++
 */
template <typename T>
class NoBinario {
 protected:
	T* dado_;  //!< Dado genérico do nó
	NoBinario<T>* esquerda;  //!< Ponteiro para o nó a esquerda
	NoBinario<T>* direita;  //!< Ponteiro para o nó a direita
	std::vector<NoBinario<T>* > elementos;  //!< Elemento acessados durante
	                                        // o percurso realizado

 public:
	/**
	 * @brief      Construtor da classe NoBinario
	 *
	 * @param      dado  Dado do nó que será criado
	 *
	 * @details    Os ponteiros esquerda e direita apontam para nullptr
	 */
	NoBinario<T>(const T& dado) {
		esquerda = nullptr;
		direita = nullptr;
		dado_ = new T(dado);
	}
	/**
	 * @brief      Destrutor NoBinario
	 */
	virtual ~NoBinario() {
		if(esquerda != nullptr) {
			delete esquerda;
		}
		if(direita != nullptr) {
			delete direita;
		}
	}
	/**
	 * @brief      Get dado
	 *
	 * @return     T dado
	 */
	T* getDado() {
		return dado_;
	}
	/**
	 * @brief      Get elementos
	 *
	 * @return     Vector elementos
	 */
	std::vector< NoBinario<T>*> getElementos() {
		return elementos;
	}
	 /**
	 * @brief      Get esquerda
	 *
	 * @return     NoBinario a esquerda
	 */
	NoBinario<T>* getEsquerda() {
		return esquerda;
	}
	 /**
	 * @brief      Get direita
	 *
	 * @return     NoBinario a direita
	 */
	NoBinario<T>* getDireita() {
		return direita;
	}
	/**
	 * @brief      Busca Binária
	 *
	 * @param      dado  Dado a ser pesquisado
	 * @param      arv   Árvore para pesquisar o dado
	 *
	 * @return     Retorna o nó que contém o dado, retornadndo um nullptr caso o
	 *             dado não exista na árvore
	 */
	T* busca(const T& dado, NoBinario<T>* arv) {
		while(arv != nullptr && *(arv->getDado()) != dado) {
			if(*(arv->getDado()) < dado) {
				arv = arv->getDireita();
			} else {
				arv = arv->getEsquerda();
			}
		}
		if(arv == nullptr) {
			throw std::runtime_error("Dado não encontrado");
		} else {
			return arv->getDado();
		}
	}
	/**
	 * @brief      Insere novo dado na árvore
	 *
	 * @param      dado  Dado a ser inserido
	 * @param      arv   Árvore a inserir o dado
	 *
	 * @return     Retorna árvore para recursão
	 */
	NoBinario<T>* inserir(const T& dado, NoBinario<T>* arv) {
		NoBinario<T> *novo = new NoBinario<T>(dado);
		if(novo == nullptr) {
			throw std::runtime_error("Sem Espaço na Memória");
		} else {
			if(dado < *(arv->getDado())) {
				if(arv->getEsquerda() == nullptr) {
					arv->esquerda = novo;
				} else {
					arv = inserir(dado, arv->getEsquerda());
				}
			} else {
				if(arv->getDireita() == nullptr) {
					arv->direita = novo;
				} else {
					arv = inserir(dado, arv->getDireita());
				}
			}
			return arv;
		}
	}
	/**
	 * @brief      Remover um nó da árvore
	 *
	 * @param      arv   Árvore
	 * @param      dado  Dado a ser removido
	 *
	 * @return     Recursão para manter a estrutura da árvore após a exclusão
	 */
	NoBinario<T>* remover(NoBinario<T>* arv, const T& dado) {
		if(arv == nullptr) {
			return arv;
		} else {
			NoBinario<T> *tmp, *filho;
			if(dado < *(arv->getDado())) {
				arv->esquerda = remover(arv->getEsquerda(), dado);
				return arv;
			} else {
				if(dado > *(arv->getDado())) {
					arv->direita = remover(arv->getDireita(), dado);
					return arv;
				} else {
					tmp = arv;
					if(arv->getDireita() != nullptr &&
						arv->getEsquerda() != nullptr) {
						tmp = minimo(arv->getDireita());
						arv->dado_ = tmp->getDado();
						arv->direita = remover(arv->getDireita(),
											  *(arv->getDado()));
						return arv;
					} else {
						if(arv->getDireita() != nullptr) {
							filho = arv->getDireita();
							return filho;
						} else {
							if(arv->getEsquerda() != nullptr) {
								filho = arv->getEsquerda();
								return filho;
							} else {
								delete tmp;
								return nullptr;
							}
						}
					}
				}
			}
		}
	}

	/**
	 * @brief      Retorna o nó com o menor valor a partir de um determinado nó
	 *
	 * @param      nodo  Nó para início da busca
	 *
	 * @return     Nó que possuí o menor valor
	 */
	NoBinario<T>* minimo(NoBinario<T>* nodo) {
		if(nodo->getEsquerda() == nullptr) {
			return nodo;
		} else {
			nodo = minimo(nodo->getEsquerda());
			return nodo;
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pela raiz, depois pelos
	 *             nós a esquerda e depois pelos nós a direita
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void preOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			elementos.push_back(nodo);
			preOrdem(nodo->getEsquerda());
			preOrdem(nodo->getDireita());
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pelos nós a esquerda,
	 *             depois pela raiz e pelos nós a direita
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void emOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			preOrdem(nodo->getEsquerda());
			elementos.push_back(nodo);
			preOrdem(nodo->getDireita());
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pelos nós a esquerda,
	 *             depois pelos nós a direita e a raiz
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void posOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			posOrdem(nodo->getEsquerda());
			posOrdem(nodo->getDireita());
			elementos.push_back(nodo);
		}
	}
};

#endif  // NO_BINARIO_HPP
<commit_msg>minor fix<commit_after>// Copyright [2016] <Salomão Rodrigues Jacinto>
#ifndef NO_BINARIO_HPP
#define NO_BINARIO_HPP

#include <cstdlib>
#include <vector>
#include <stdexcept>

/**
 * @brief      Implementação de uma estrutura de Árvore Binária em C++
 */
template <typename T>
class NoBinario {
 protected:
	T* dado_;  //!< Dado genérico do nó
	NoBinario<T>* esquerda;  //!< Ponteiro para o nó a esquerda
	NoBinario<T>* direita;  //!< Ponteiro para o nó a direita
	std::vector<NoBinario<T>* > elementos;  //!< Elemento acessados durante
	                                        // o percurso realizado

 public:
	/**
	 * @brief      Construtor da classe NoBinario
	 *
	 * @param      dado  Dado do nó que será criado
	 *
	 * @details    Os ponteiros esquerda e direita apontam para nullptr
	 */
	NoBinario<T>(const T& dado) {
		esquerda = nullptr;
		direita = nullptr;
		dado_ = new T(dado);
	}
	/**
	 * @brief      Destrutor NoBinario
	 */
	virtual ~NoBinario() {
		delete dado_;
		if(esquerda != nullptr) {
			delete esquerda;
		}
		if(direita != nullptr) {
			delete direita;
		}
	}
	/**
	 * @brief      Get dado
	 *
	 * @return     T dado
	 */
	T* getDado() {
		return dado_;
	}
	/**
	 * @brief      Get elementos
	 *
	 * @return     Vector elementos
	 */
	std::vector< NoBinario<T>*> getElementos() {
		return elementos;
	}
	 /**
	 * @brief      Get esquerda
	 *
	 * @return     NoBinario a esquerda
	 */
	NoBinario<T>* getEsquerda() {
		return esquerda;
	}
	 /**
	 * @brief      Get direita
	 *
	 * @return     NoBinario a direita
	 */
	NoBinario<T>* getDireita() {
		return direita;
	}
	/**
	 * @brief      Busca Binária
	 *
	 * @param      dado  Dado a ser pesquisado
	 * @param      arv   Árvore para pesquisar o dado
	 *
	 * @return     Retorna o nó que contém o dado, retornadndo um nullptr caso o
	 *             dado não exista na árvore
	 */
	T* busca(const T& dado, NoBinario<T>* arv) {
		while(arv != nullptr && *(arv->getDado()) != dado) {
			if(*(arv->getDado()) < dado) {
				arv = arv->getDireita();
			} else {
				arv = arv->getEsquerda();
			}
		}
		if(arv == nullptr) {
			throw std::runtime_error("Dado não encontrado");
		} else {
			return arv->getDado();
		}
	}
	/**
	 * @brief      Insere novo dado na árvore
	 *
	 * @param      dado  Dado a ser inserido
	 * @param      arv   Árvore a inserir o dado
	 *
	 * @return     Retorna árvore para recursão
	 */
	NoBinario<T>* inserir(const T& dado, NoBinario<T>* arv) {
		if(dado < *(arv->getDado())) {
			if(arv->getEsquerda() == nullptr) {
				arv->esquerda = new NoBinario<T>(dado);
			} else {
				arv = inserir(dado, arv->getEsquerda());
			}
		} else {
			if(arv->getDireita() == nullptr) {
				arv->direita = new NoBinario<T>(dado);
			} else {
				arv = inserir(dado, arv->getDireita());
			}
		}
		return arv;
	}
	/**
	 * @brief      Remover um nó da árvore
	 *
	 * @param      arv   Árvore
	 * @param      dado  Dado a ser removido
	 *
	 * @return     Recursão para manter a estrutura da árvore após a exclusão
	 */
	NoBinario<T>* remover(NoBinario<T>* arv, const T& dado) {
		if(arv == nullptr) {
			return arv;
		} else {
			NoBinario<T> *tmp, *filho;
			if(dado < *(arv->getDado())) {
				arv->esquerda = remover(arv->getEsquerda(), dado);
				return arv;
			} else {
				if(dado > *(arv->getDado())) {
					arv->direita = remover(arv->getDireita(), dado);
					return arv;
				} else {
					tmp = arv;
					if(arv->getDireita() != nullptr &&
						arv->getEsquerda() != nullptr) {
						tmp = minimo(arv->getDireita());
						arv->dado_ = tmp->getDado();
						arv->direita = remover(arv->getDireita(),
											  *(arv->getDado()));
						return arv;
					} else {
						if(arv->getDireita() != nullptr) {
							filho = arv->getDireita();
							return filho;
						} else {
							if(arv->getEsquerda() != nullptr) {
								filho = arv->getEsquerda();
								return filho;
							} else {
								delete tmp;
								return nullptr;
							}
						}
					}
				}
			}
		}
	}

	/**
	 * @brief      Retorna o nó com o menor valor a partir de um determinado nó
	 *
	 * @param      nodo  Nó para início da busca
	 *
	 * @return     Nó que possuí o menor valor
	 */
	NoBinario<T>* minimo(NoBinario<T>* nodo) {
		if(nodo->getEsquerda() == nullptr) {
			return nodo;
		} else {
			nodo = minimo(nodo->getEsquerda());
			return nodo;
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pela raiz, depois pelos
	 *             nós a esquerda e depois pelos nós a direita
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void preOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			elementos.push_back(nodo);
			preOrdem(nodo->getEsquerda());
			preOrdem(nodo->getDireita());
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pelos nós a esquerda,
	 *             depois pela raiz e pelos nós a direita
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void emOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			preOrdem(nodo->getEsquerda());
			elementos.push_back(nodo);
			preOrdem(nodo->getDireita());
		}
	}
	/**
	 * @brief      Organiza os nós em um vetor começando pelos nós a esquerda,
	 *             depois pelos nós a direita e a raiz
	 *
	 * @param      nodo  Nó para início da ordenação
	 */
	void posOrdem(NoBinario<T>* nodo) {
		if(nodo != nullptr) {
			posOrdem(nodo->getEsquerda());
			posOrdem(nodo->getDireita());
			elementos.push_back(nodo);
		}
	}
};

#endif  // NO_BINARIO_HPP
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Core/Common.h"
#include "Core/Assembler.h"
#include "Archs/MIPS/Mips.h"
#include "Commands/CDirectiveFile.h"
#include "Tests.h"

#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__)
#define ARMIPSNAME "ARMIPS64"
#else
#define ARMIPSNAME "ARMIPS"
#endif

int wmain(int argc, wchar_t* argv[])
{
	ArmipsArguments parameters;

#ifdef ARMIPS_TESTS
	std::wstring name;

	if (argc < 2)
		return !runTests(L"Tests");
	else
		return !runTests(argv[1]);
#endif

	StringList arguments = getStringListFromArray(argv,argc);

	if (arguments.size() < 2)
	{
		Logger::printLine(L"%s Assembler v%d.%d.%d (%s %s) by Kingcom",
			ARMIPSNAME,ARMIPS_VERSION_MAJOR,ARMIPS_VERSION_MINOR,ARMIPS_VERSION_REVISION,__DATE__,__TIME__);
		Logger::printLine(L"Usage: %s file.asm [-temp temp.txt] [-sym symfile.sym]", argv[0]);
		return 1;
	}

	parameters.inputFileName = arguments[1];

	// turn it into an absolute path
	if (isAbsolutePath(parameters.inputFileName) == false)
		parameters.inputFileName = formatString(L"%s/%s",getCurrentDirectory(),arguments[1]);

	if (fileExists(parameters.inputFileName) == false)
	{
		Logger::printLine(L"File %S not found\n",arguments[1]);
		return 1;
	}

	size_t argpos = 2;
	bool printTime = false;
	while (argpos < arguments.size())
	{
		if (arguments[argpos] == L"-temp")
		{
			parameters.tempFileName = arguments[argpos+1];
			argpos += 2;
		} else if (arguments[argpos] == L"-sym")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 1;
			argpos += 2;
		} else if (arguments[argpos] == L"-sym2")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 2;
			argpos += 2;
		} else if (arguments[argpos] == L"-erroronwarning")
		{
			parameters.errorOnWarning = true;
			argpos += 1;
		} else if (arguments[argpos] == L"-equ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = arguments[argpos + 2];
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-strequ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = formatString(L"\"%s\"",arguments[argpos + 2]);
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-root")
		{
			changeDirectory(arguments[argpos + 1]);
			argpos += 2;
		} else {
			Logger::printLine(L"Invalid parameter %S\n",arguments[argpos]);
			return 1;
		}
	}

	bool result = runArmips(parameters);

	if (result == false)
	{
		Logger::printLine(L"Aborting.");
		return 1;
	}

	return 0;
}

#ifndef _WIN32

int main(int argc, char* argv[])
{
	// convert input to wstring
	std::vector<std::wstring> wideStrings;
	for (int i = 0; i < argc; i++)
	{
		std::wstring str = convertUtf8ToWString(argv[i]);
		wideStrings.push_back(str);
	}

	// create argv replacement
	wchar_t** wargv = new wchar_t*[argc];
	for (int i = 0; i < argc; i++)
	{
		wargv[i] = (wchar_t*) wideStrings[i].c_str();
	}

	int result = wmain(argc,wargv);

	delete[] wargv;
	return result;
}

#endif
<commit_msg>Add deprecation message for -time flag<commit_after>#include "stdafx.h"
#include "Core/Common.h"
#include "Core/Assembler.h"
#include "Archs/MIPS/Mips.h"
#include "Commands/CDirectiveFile.h"
#include "Tests.h"

#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__)
#define ARMIPSNAME "ARMIPS64"
#else
#define ARMIPSNAME "ARMIPS"
#endif

int wmain(int argc, wchar_t* argv[])
{
	ArmipsArguments parameters;

#ifdef ARMIPS_TESTS
	std::wstring name;

	if (argc < 2)
		return !runTests(L"Tests");
	else
		return !runTests(argv[1]);
#endif

	StringList arguments = getStringListFromArray(argv,argc);

	if (arguments.size() < 2)
	{
		Logger::printLine(L"%s Assembler v%d.%d.%d (%s %s) by Kingcom",
			ARMIPSNAME,ARMIPS_VERSION_MAJOR,ARMIPS_VERSION_MINOR,ARMIPS_VERSION_REVISION,__DATE__,__TIME__);
		Logger::printLine(L"Usage: %s file.asm [-temp temp.txt] [-sym symfile.sym]", argv[0]);
		return 1;
	}

	parameters.inputFileName = arguments[1];

	// turn it into an absolute path
	if (isAbsolutePath(parameters.inputFileName) == false)
		parameters.inputFileName = formatString(L"%s/%s",getCurrentDirectory(),arguments[1]);

	if (fileExists(parameters.inputFileName) == false)
	{
		Logger::printLine(L"File %S not found\n",arguments[1]);
		return 1;
	}

	size_t argpos = 2;
	bool printTime = false;
	while (argpos < arguments.size())
	{
		if (arguments[argpos] == L"-temp")
		{
			parameters.tempFileName = arguments[argpos+1];
			argpos += 2;
		} else if (arguments[argpos] == L"-sym")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 1;
			argpos += 2;
		} else if (arguments[argpos] == L"-sym2")
		{
			parameters.symFileName = arguments[argpos+1];
			parameters.symFileVersion = 2;
			argpos += 2;
		} else if (arguments[argpos] == L"-erroronwarning")
		{
			parameters.errorOnWarning = true;
			argpos += 1;
		} else if (arguments[argpos] == L"-equ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = arguments[argpos + 2];
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-strequ")
		{
			EquationDefinition def;
			def.name = arguments[argpos + 1];
			def.value = formatString(L"\"%s\"",arguments[argpos + 2]);
			parameters.equList.push_back(def);
			argpos += 3;
		} else if (arguments[argpos] == L"-time")
		{
			Logger::printError(Logger::Warning,L"-time flag is deprecated");
			argpos += 1;
		} else if (arguments[argpos] == L"-root")
		{
			changeDirectory(arguments[argpos + 1]);
			argpos += 2;
		} else {
			Logger::printLine(L"Invalid parameter %S\n",arguments[argpos]);
			return 1;
		}
	}

	bool result = runArmips(parameters);

	if (result == false)
	{
		Logger::printLine(L"Aborting.");
		return 1;
	}

	return 0;
}

#ifndef _WIN32

int main(int argc, char* argv[])
{
	// convert input to wstring
	std::vector<std::wstring> wideStrings;
	for (int i = 0; i < argc; i++)
	{
		std::wstring str = convertUtf8ToWString(argv[i]);
		wideStrings.push_back(str);
	}

	// create argv replacement
	wchar_t** wargv = new wchar_t*[argc];
	for (int i = 0; i < argc; i++)
	{
		wargv[i] = (wchar_t*) wideStrings[i].c_str();
	}

	int result = wmain(argc,wargv);

	delete[] wargv;
	return result;
}

#endif
<|endoftext|>


<commit_before>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 background += cvQueryFrame(capture);
 background += cvQueryFrame(capture);
 background += cvQueryFrame(capture);
 background += cvQueryFrame(capture);
 background = background/5;
 blur(background, background, Size(50,50));
 imshow("background", background);

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  //imshow("webcam", image);

// thresholds on dark regions

  Mat gray, blurred_gray, threshold_gray;
  cvtColor(image, gray, CV_BGR2GRAY);

  blur(gray, blurred_gray, Size(width/10,height/20));
  equalizeHist(blurred_gray, blurred_gray);
  bitwise_not(blurred_gray, blurred_gray);
  threshold(blurred_gray, threshold_gray, 210, 1, THRESH_BINARY);
//  imshow("threshold", threshold_gray);
// threshold_gray has 1 for probable foreground
// has 0 for idkwtf

  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 220, 1, THRESH_BINARY);
//  imshow("canny", canny);

  Mat certainBackground;
  bitwise_or(canny, threshold_gray, certainBackground);
  Mat kernel = Mat::ones(15, 15, CV_8UC1);
  morphologyEx(certainBackground, certainBackground, MORPH_CLOSE, kernel, Point(-1,-1), 3);
// certainBackground has 0 for definitely not rift
// and 1 for no clue what it is
  imshow("image", gray.mul(certainBackground));

  Mat flow;
  blur(image, flow, Size(50,50));
  absdiff(flow.mul(certainBackground), background.mul(certainBackground), flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  blur(flow, flow, Size(50,50));
  equalizeHist(flow, flow);
  imshow("flow", gray.mul(flow)/255);

/*
  bitwise_not(gray,gray);
  Mat mask = threshold_gray.mul(gray);
  imshow("mask", mask);

  Moments lol = moments(mask, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));
 imshow("background", background);

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  //imshow("webcam", image);

// thresholds on dark regions

  Mat gray, blurred_gray, threshold_gray;
  cvtColor(image, gray, CV_BGR2GRAY);

  blur(gray, blurred_gray, Size(width/10,height/20));
  equalizeHist(blurred_gray, blurred_gray);
  bitwise_not(blurred_gray, blurred_gray);
  threshold(blurred_gray, threshold_gray, 210, 1, THRESH_BINARY);
//  imshow("threshold", threshold_gray);
// threshold_gray has 1 for probable foreground
// has 0 for idkwtf

  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 220, 1, THRESH_BINARY);
//  imshow("canny", canny);

  Mat certainBackground;
  bitwise_or(canny, threshold_gray, certainBackground);
  Mat kernel = Mat::ones(15, 15, CV_8UC1);
  morphologyEx(certainBackground, certainBackground, MORPH_CLOSE, kernel, Point(-1,-1), 3);
// certainBackground has 0 for definitely not rift
// and 1 for no clue what it is
  imshow("image", gray.mul(certainBackground));

  Mat channels[3];
  Mat cB;
  channels[0] = certainBackground;
  channels[1] = certainBackground;
  channels[2] = certainBackground;
  merge(channels, 3, cB);
  Mat flow;
  blur(image, flow, Size(50,50));
  absdiff(flow.mul(cB), background.mul(cB), flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  blur(flow, flow, Size(50,50));
  equalizeHist(flow, flow);
  Mat mask = flow;

/*
  bitwise_not(gray,gray);
  Mat mask = threshold_gray.mul(gray);
  imshow("mask", mask);
*/
  Moments lol = moments(mask, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground
 Mat acfg_t(256, 256, CV_8UC3, Scalar(0));
// accumulated foreground threshold
 Mat defacbg(256, 256, CV_8UC3, Scalar(0,0,0));
 Mat iee(cvQueryFrame(capture));
 resize(iee, defacbg, Size(256,256));
 imshow("iee", defacbg);
/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 215, 1, THRESH_BINARY);
  dilate(gr_m, gr_m, ellipticKernel(23));
  erode(gr_m, gr_m, ellipticKernel(45));

//  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  fl_m = acbg_m.mul(fl_m);
  threshold(fl_m, fl_m, 45, 1, THRESH_BINARY_INV);
  erode(fl_m, fl_m, ellipticKernel(51));
//  imshow("flow mask", fl_m*255);

  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
  bitwise_or(gr_m, bg_m, bg_m);
  imshow("bgm", bg_m*255);

// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
//  imshow("bg_m3", bg_m3*255);
  acbg = acbg.mul(Scalar(1,1,1)-bg_m3) + (acbg/2+img_256/2).mul(bg_m3);
//  imshow("acbg", acbg);

//  imshow("bg mask", gray_256.mul(1-bg_m));

/*
 // do some stuff with foreground and so on here

  Mat haar_m;
// bitwise_and(1 - bg_m, fg_m, haar_m);
  haar_m = 1 - bg_m;

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat thingy;
  resize(gray, thingy, Size(width/scale, height/scale));
  equalizeHist(thingy, thingy);
///////////////////
// need to change this after foreground stuff gets written

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  bitwise_and(haar_m, thingy, thingy);
/////////////////

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rect_image(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   rect_image += new_rect;
  }

  double min_val, max_val;
  minMaxLoc(rect_image, &min_val, &max_val);

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

  Mat rect_thresh;
  threshold(rect_image, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground
 Mat acfg_t(256, 256, CV_8UC3, Scalar(0));
// accumulated foreground threshold

/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 215, 1, THRESH_BINARY);
  dilate(gr_m, gr_m, ellipticKernel(23));
  erode(gr_m, gr_m, ellipticKernel(45));

//  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  fl_m = acbg_m.mul(fl_m);
  threshold(fl_m, fl_m, 45, 1, THRESH_BINARY_INV);
  erode(fl_m, fl_m, ellipticKernel(51));
//  imshow("flow mask", fl_m*255);

  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
  bitwise_or(gr_m, bg_m, bg_m);
//  imshow("bgm", bg_m*255);

// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
//  imshow("bg_m3", bg_m3*255);
  acbg = acbg.mul(Scalar(1,1,1)-bg_m3) + (acbg/2+img_256/2).mul(bg_m3);
//  imshow("acbg", acbg);

//  imshow("bg mask", gray_256.mul(1-bg_m));

 // do some stuff with foreground and so on here

  Mat haar_m;
// bitwise_and(1 - bg_m, fg_m, haar_m);
  haar_m = 1 - bg_m;

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat thingy;
  resize(gray, thingy, Size(width/scale, height/scale));
  equalizeHist(thingy, thingy);
///////////////////
// need to change this after foreground stuff gets written

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  thingy = thingy.mul(haar_m);
/////////////////

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rect_image(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   rect_image += new_rect;
  }

  double min_val, max_val;
  minMaxLoc(rect_image, &min_val, &max_val);

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

  Mat rect_thresh;
  threshold(rect_image, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<|endoftext|>


<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas which have not changed much
// this is horrible with new background; redo it
// the way it works with dk2 is very different from without
// since eyes are detected by mouth cascade but not dk2
  Mat flow(height, width, CV_8UC1, 1);

  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  threshold(flow, flow, 6, 1, THRESH_BINARY);
  morphFast(flow, 100, 40, 0);//needs less without dk2
  imshow("flow mask", gray.mul(flow));
  times[2] = getMilliseconds() - timenow;
  timenow = getMilliseconds();
  flow = Mat(height, width, CV_8UC1, 1);

// this mask gets anything kind of dark (DK2) and dilates
// works *great*
  Mat kindofdark(height, width, CV_8UC1, 1);
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));
  times[3] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// combine mask with its opening
  Mat mask = flow.mul(kindofdark);
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat smallKernel = ellipticKernel(69,79);
  erode(smallMask0, smallMask1, smallKernel);
  dilate(smallMask1, smallMask1, smallKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
//  imshow("morph mask", gray.mul(mask));
  times[4] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// run haar classifier on nonflow parts of image
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);
  Mat dilatedMask;
  dilate(smallMask1, dilatedMask, smallKernel);
//  dilate(dilatedMask, dilatedMask, smallKernel);
  resize(dilatedMask, dilatedMask, Size(width, height));
  resize(gray.mul(dilatedMask), classifyThis, Size(width/scale,height/scale));
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rectImage(height, width, CV_8UC1, Scalar(0));
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   Mat newRect(height, width, CV_8UC1, Scalar(0));
   rectangle(newRect, scaled, Scalar(1), CV_FILLED);
   rectImage += newRect;
  }
  double minVal, maxVal;//ignore minVal, it'll be 0
  minMaxLoc(rectImage, &minVal, &maxVal);
  Mat recThresh, recBinary;
  threshold(rectImage, recThresh, maxVal*0.9, 1, THRESH_BINARY);
// what's the point of this v ?
  threshold(rectImage, recBinary, 1, 1, THRESH_BINARY);
  bitwise_and(recBinary, mask, mask);
  times[5] = getMilliseconds() - timenow;
  timenow = getMilliseconds();
  imshow("mouth", recThresh.mul(gray));

/*
  Moments lol = moments(recThresh, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

// update background with new morph mask

  Mat mask_;
  subtract(1, mask ,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)*0.75 + blurred_img.mul(mask3_)*0.25);
  times[6] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

  imshow("bg", background);

  for (int i=0; i<7; i++) {
   printf("%llu , ", times[i]);
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas which have not changed much
// this is horrible with new background; redo it
// the way it works with dk2 is very different from without
// since eyes are detected by mouth cascade but not dk2
  Mat flow(height, width, CV_8UC1, 1);

  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  threshold(flow, flow, 6, 1, THRESH_BINARY);
  morphFast(flow, 100, 40, 0);//needs less without dk2
  imshow("flow mask", gray.mul(flow));
  times[2] = getMilliseconds() - timenow;
  timenow = getMilliseconds();
  flow = Mat(height, width, CV_8UC1, 1);

// this mask gets anything kind of dark (DK2) and dilates
// works *great*
  Mat kindofdark(height, width, CV_8UC1, 1);
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));
  times[3] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// combine mask with its opening
  Mat mask = flow.mul(kindofdark);
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat smallKernel = ellipticKernel(69,79);
  erode(smallMask0, smallMask1, smallKernel);
  dilate(smallMask1, smallMask1, smallKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
//  imshow("morph mask", gray.mul(mask));
  times[4] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

// run haar classifier on nonflow parts of image
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);
  Mat dilatedMask;
  dilate(smallMask1, dilatedMask, smallKernel);
//  dilate(dilatedMask, dilatedMask, smallKernel);
  resize(dilatedMask, dilatedMask, Size(width, height));
  resize(gray.mul(dilatedMask), classifyThis, Size(width/scale,height/scale));
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rectImage(height, width, CV_8UC1, Scalar(0));
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   Mat newRect(height, width, CV_8UC1, Scalar(0));
   rectangle(newRect, scaled, Scalar(1), CV_FILLED);
   rectImage += newRect;
  }
  double minVal, maxVal;//ignore minVal, it'll be 0
  minMaxLoc(rectImage, &minVal, &maxVal);
  Mat recThresh, recBinary;
  threshold(rectImage, recThresh, maxVal*0.9, 1, THRESH_BINARY);
  threshold(rectImage, recBinary, 1, 1, THRESH_BINARY);
  imshow("recbin", recBinary*255);
  bitwise_and(recBinary, mask, mask);
  times[5] = getMilliseconds() - timenow;
  timenow = getMilliseconds();
  imshow("mouth", recThresh.mul(gray));

/*
  Moments lol = moments(recThresh, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

// update background with new morph mask

  Mat mask_;
  subtract(1, mask ,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)*0.75 + blurred_img.mul(mask3_)*0.25);
  times[6] = getMilliseconds() - timenow;
  timenow = getMilliseconds();

  imshow("bg", background);

  for (int i=0; i<7; i++) {
   printf("%llu , ", times[i]);
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdint.h>

#include <vector>

#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/schema/schema_generated.h"

namespace tflite {
namespace {

using ::testing::ElementsAre;

template <typename T>
class FloorModModel : public SingleOpModel {
 public:
  FloorModModel(const TensorData& input1, const TensorData& input2,
                const TensorData& output) {
    input1_ = AddInput(input1);
    input2_ = AddInput(input2);
    output_ = AddOutput(output);
    SetBuiltinOp(BuiltinOperator_FLOOR_MOD, BuiltinOptions_FloorModOptions,
                 CreateFloorModOptions(builder_).Union());
    BuildInterpreter({GetShape(input1_), GetShape(input2_)});
  }

  int input1() { return input1_; }
  int input2() { return input2_; }

  std::vector<T> GetOutput() { return ExtractVector<T>(output_); }
  std::vector<int> GetOutputShape() { return GetTensorShape(output_); }

 private:
  int input1_;
  int input2_;
  int output_;
};

TEST(FloorModModel, Simple) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, 9, 11, 3});
  model.PopulateTensor<int32_t>(model.input2(), {2, 2, 3, 4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, 2, 3));
}

TEST(FloorModModel, NegativeValue) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<int32_t>(model.input2(), {2, 2, -3, -4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, -2, -1));
}

TEST(FloorModModel, BroadcastFloorMod) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1}}, {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<int32_t>(model.input2(), {-3});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(-2, 0, -2, -2));
}

TEST(FloorModModel, Int64WithBroadcast) {
  FloorModModel<int64_t> model({TensorType_INT64, {1, 2, 2, 1}},
                               {TensorType_INT64, {1}}, {TensorType_INT64, {}});
  model.PopulateTensor<int64_t>(model.input1(), {10, -9, -11, (1LL << 34) + 9});
  model.PopulateTensor<int64_t>(model.input2(), {-(1LL << 33)});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(),
              ElementsAre(-8589934582, -9, -11, -8589934583));
}

TEST(FloorModModel, FloatSimple) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, 9, 11, 3});
  model.PopulateTensor<float>(model.input2(), {2, 2, 3, 4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, 2, 3));
}

TEST(FloorModModel, FloatNegativeValue) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<float>(model.input2(), {2, 2, -3, -4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, -2, -1));
}

TEST(FloorModModel, FloatBroadcastFloorMod) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<float>(model.input2(), {-3});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(-2, 0, -2, -2));
}

}  // namespace
}  // namespace tflite
<commit_msg>Remove include files that do not pass backend tests<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <stdint.h>

#include <vector>

#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/schema/schema_generated.h"

namespace tflite {
namespace {

using ::testing::ElementsAre;

template <typename T>
class FloorModModel : public SingleOpModel {
 public:
  FloorModModel(const TensorData& input1, const TensorData& input2,
                const TensorData& output) {
    input1_ = AddInput(input1);
    input2_ = AddInput(input2);
    output_ = AddOutput(output);
    SetBuiltinOp(BuiltinOperator_FLOOR_MOD, BuiltinOptions_FloorModOptions,
                 CreateFloorModOptions(builder_).Union());
    BuildInterpreter({GetShape(input1_), GetShape(input2_)});
  }

  int input1() { return input1_; }
  int input2() { return input2_; }

  std::vector<T> GetOutput() { return ExtractVector<T>(output_); }
  std::vector<int> GetOutputShape() { return GetTensorShape(output_); }

 private:
  int input1_;
  int input2_;
  int output_;
};

TEST(FloorModModel, Simple) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, 9, 11, 3});
  model.PopulateTensor<int32_t>(model.input2(), {2, 2, 3, 4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, 2, 3));
}

TEST(FloorModModel, NegativeValue) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<int32_t>(model.input2(), {2, 2, -3, -4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, -2, -1));
}

TEST(FloorModModel, BroadcastFloorMod) {
  FloorModModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
                               {TensorType_INT32, {1}}, {TensorType_INT32, {}});
  model.PopulateTensor<int32_t>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<int32_t>(model.input2(), {-3});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(-2, 0, -2, -2));
}

TEST(FloorModModel, Int64WithBroadcast) {
  FloorModModel<int64_t> model({TensorType_INT64, {1, 2, 2, 1}},
                               {TensorType_INT64, {1}}, {TensorType_INT64, {}});
  model.PopulateTensor<int64_t>(model.input1(), {10, -9, -11, (1LL << 34) + 9});
  model.PopulateTensor<int64_t>(model.input2(), {-(1LL << 33)});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(),
              ElementsAre(-8589934582, -9, -11, -8589934583));
}

TEST(FloorModModel, FloatSimple) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, 9, 11, 3});
  model.PopulateTensor<float>(model.input2(), {2, 2, 3, 4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, 2, 3));
}

TEST(FloorModModel, FloatNegativeValue) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<float>(model.input2(), {2, 2, -3, -4});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(0, 1, -2, -1));
}

TEST(FloorModModel, FloatBroadcastFloorMod) {
  FloorModModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
                             {TensorType_FLOAT32, {1}},
                             {TensorType_FLOAT32, {}});
  model.PopulateTensor<float>(model.input1(), {10, -9, -11, 7});
  model.PopulateTensor<float>(model.input2(), {-3});
  model.Invoke();
  EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
  EXPECT_THAT(model.GetOutput(), ElementsAre(-2, 0, -2, -2));
}

}  // namespace
}  // namespace tflite
<|endoftext|>


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

#include "account-item.h"

#include "accounts-list-model.h"

#include <kdebug.h>

#include <QtCore/QTimer>

#include <TelepathyQt4/Client/Account>
#include <TelepathyQt4/Client/PendingOperation>
#include <TelepathyQt4/Client/PendingReadyAccount>

AccountItem::AccountItem(Telepathy::Client::Account *account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account)
{
    // We should look to see if the "account" instance we are passed is ready
    // yet. If not, we should get it ready now.
    // FIXME: What features should we check are ready?
    if(m_account->isReady())
    {
        QTimer::singleShot(0, this, SIGNAL(ready()));
    }
    else
    {
        // FIXME: What features should we get ready with?
        connect(m_account->becomeReady(), SIGNAL(finished(Telepathy::Client::PendingOperation*)),
                this, SLOT(onBecomeReadyFinished(Telepathy::Client::PendingOperation*)), Qt::QueuedConnection);
    }
}

AccountItem::~AccountItem()
{
    // TODO: Implement me...
}

void AccountItem::onBecomeReadyFinished(Telepathy::Client::PendingOperation *op)
{
     Q_ASSERT(op->isFinished());

    Telepathy::Client::PendingReadyAccount *pra = qobject_cast<Telepathy::Client::PendingReadyAccount*>(op);
    Q_ASSERT(0 != pra);

    if(pra->isError())
    {
        kDebug() << "An error occurred in making and Account ready.";
        return;
    }
    else
    {
        kDebug() << "An Account became ready successfully.";
        Q_EMIT ready();
    }
}

#include "account-item.moc"

<commit_msg>Seems it only took one more line to make the AccountItem handle the account becoming ready completely.<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account-item.h"

#include "accounts-list-model.h"

#include <kdebug.h>

#include <QtCore/QTimer>

#include <TelepathyQt4/Client/Account>
#include <TelepathyQt4/Client/PendingOperation>
#include <TelepathyQt4/Client/PendingReadyAccount>

AccountItem::AccountItem(Telepathy::Client::Account *account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account)
{
    // We should look to see if the "account" instance we are passed is ready
    // yet. If not, we should get it ready now.
    // FIXME: What features should we check are ready?
    if(m_account->isReady())
    {
        QTimer::singleShot(0, this, SIGNAL(ready()));
    }
    else
    {
        // FIXME: What features should we get ready with?
        connect(m_account->becomeReady(), SIGNAL(finished(Telepathy::Client::PendingOperation*)),
                this, SLOT(onBecomeReadyFinished(Telepathy::Client::PendingOperation*)), Qt::QueuedConnection);
    }
}

AccountItem::~AccountItem()
{
    // TODO: Implement me...
}

void AccountItem::onBecomeReadyFinished(Telepathy::Client::PendingOperation *op)
{
     Q_ASSERT(op->isFinished());

    Telepathy::Client::PendingReadyAccount *pra = qobject_cast<Telepathy::Client::PendingReadyAccount*>(op);
    Q_ASSERT(0 != pra);

    if(pra->isError())
    {
        kDebug() << "An error occurred in making and Account ready.";
        return;
    }
    else
    {
        kDebug() << "An Account became ready successfully.";
        m_account = pra->account();
        // FIXME: What features should we check its ready with?
        Q_ASSERT(m_account->isReady());
        Q_EMIT ready();
    }
}

#include "account-item.moc"

<|endoftext|>


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

#include "account-item.h"

#include "accounts-list-model.h"
#include "edit-account-dialog.h"

#include <KTp/error-dictionary.h>

#include <KApplication>
#include <KDebug>
#include <KIcon>
#include <KLocalizedString>

#include <QtCore/QTimer>
#include <QtGui/QPainter>

#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <KPixmapSequence>

AccountItem::AccountItem(const Tp::AccountPtr &account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account),
   m_icon(new KIcon())
{
    //connect AccountPtr signals to AccountItem signals
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(displayNameChanged(QString)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(iconNameChanged(QString)),
            SLOT(generateIcon()));
    connect(m_account.data(),
            SIGNAL(removed()),
            SIGNAL(removed()));
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SLOT(generateIcon()));

    generateIcon();
}

AccountItem::~AccountItem()
{
    delete m_icon;
}

Tp::AccountPtr AccountItem::account() const
{
    return m_account;
}

void AccountItem::remove()
{
    kDebug() << "Account about to be removed";

    Tp::PendingOperation *op = m_account->remove();
    connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountRemoved(Tp::PendingOperation*)));
}

const KIcon& AccountItem::icon() const
{
    Q_ASSERT(m_icon != 0);

    return *m_icon;
}

const QString AccountItem::connectionStateString() const
{
    if (m_account->isEnabled()) {
        switch (m_account->connectionStatus()) {
        case Tp::ConnectionStatusConnected:
            return i18n("Online");
        case Tp::ConnectionStatusConnecting:
            return i18nc("This is a connection state", "Connecting");
        case Tp::ConnectionStatusDisconnected:
            return i18nc("This is a connection state", "Disconnected");
        default:
            return i18nc("This is an unknown connection state", "Unknown");
        }
    } else {
        return i18nc("This is a disabled account", "Disabled");
    }
}

const KIcon AccountItem::connectionStateIcon() const
{
    switch (m_account->connectionStatus()) {
    case Tp::ConnectionStatusConnected:
        return KIcon(QLatin1String("user-online"));
    case Tp::ConnectionStatusConnecting:
        //imho this is not really worth animating, but feel free to play around..
        return KIcon(KPixmapSequence(QLatin1String("process-working"), 22).frameAt(0));
    case Tp::ConnectionStatusDisconnected:
        return KIcon(QLatin1String("user-offline"));
    default:
        return KIcon(QLatin1String("user-offline"));
    }
}

const QString AccountItem::connectionStatusReason() const
{
    if (!m_account->isEnabled()) {
        return i18n("Account disabled - Click checkbox to enable");
    }
    else if (m_account->connectionStatusReason() == Tp::ConnectionStatusReasonRequested) {
        return QString();
    }
    else {
        return KTp::ErrorDictionary::displayShortErrorMessage(m_account->connectionError());
    }
}

const QString AccountItem::connectionProtocolName() const
{
    return m_account->protocolName();
}

void AccountItem::generateIcon()
{
    QString iconPath = account()->iconName();

    //if the icon has not been set, we use the protocol icon
    if (iconPath.isEmpty()) {
        iconPath = QString::fromLatin1("im-%1").arg(account()->protocolName());
    }

    delete m_icon;
    if (m_account->isEnabled()) {
        m_icon = new KIcon(iconPath);
    } else {
        m_icon = new KIcon(KIconLoader::global()->loadIcon(iconPath, KIconLoader::Desktop, 32, KIconLoader::DisabledState));
    }

    if (!account()->isValid()) {
        //we paint a warning symbol in the right-bottom corner
        QPixmap pixmap = m_icon->pixmap(32, 32);
        QPainter painter(&pixmap);
        KIcon(QLatin1String("dialog-error")).paint(&painter, 15, 15, 16, 16);

        delete m_icon;
        m_icon = new KIcon(pixmap);
    }

    Q_EMIT(updated());
}

void AccountItem::onAccountRemoved(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "An error occurred removing the Account."
                 << op->errorName()
                 << op->errorMessage();
        return;
    }
}

void AccountItem::onTitleForCustomPages(QString mandatoryPage, QList<QString> optionalPage)
{
    Q_EMIT setTitleForCustomPages(mandatoryPage, optionalPage);
}

Tp::ConnectionStatus AccountItem::connectionStatus() const
{
    return m_account->connectionStatus();
}

#include "account-item.moc"
<commit_msg>Do not return an icon for disabled accounts<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <info@collabora.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account-item.h"

#include "accounts-list-model.h"
#include "edit-account-dialog.h"

#include <KTp/error-dictionary.h>

#include <KApplication>
#include <KDebug>
#include <KIcon>
#include <KLocalizedString>

#include <QtCore/QTimer>
#include <QtGui/QPainter>

#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <KPixmapSequence>

AccountItem::AccountItem(const Tp::AccountPtr &account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account),
   m_icon(new KIcon())
{
    //connect AccountPtr signals to AccountItem signals
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(displayNameChanged(QString)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(iconNameChanged(QString)),
            SLOT(generateIcon()));
    connect(m_account.data(),
            SIGNAL(removed()),
            SIGNAL(removed()));
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SLOT(generateIcon()));

    generateIcon();
}

AccountItem::~AccountItem()
{
    delete m_icon;
}

Tp::AccountPtr AccountItem::account() const
{
    return m_account;
}

void AccountItem::remove()
{
    kDebug() << "Account about to be removed";

    Tp::PendingOperation *op = m_account->remove();
    connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountRemoved(Tp::PendingOperation*)));
}

const KIcon& AccountItem::icon() const
{
    Q_ASSERT(m_icon != 0);

    return *m_icon;
}

const QString AccountItem::connectionStateString() const
{
    if (m_account->isEnabled()) {
        switch (m_account->connectionStatus()) {
        case Tp::ConnectionStatusConnected:
            return i18n("Online");
        case Tp::ConnectionStatusConnecting:
            return i18nc("This is a connection state", "Connecting");
        case Tp::ConnectionStatusDisconnected:
            return i18nc("This is a connection state", "Disconnected");
        default:
            return i18nc("This is an unknown connection state", "Unknown");
        }
    } else {
        return i18nc("This is a disabled account", "Disabled");
    }
}

const KIcon AccountItem::connectionStateIcon() const
{
    if (m_account->isEnabled()) {
        switch (m_account->connectionStatus()) {
        case Tp::ConnectionStatusConnected:
            return KIcon(QLatin1String("user-online"));
        case Tp::ConnectionStatusConnecting:
            //imho this is not really worth animating, but feel free to play around..
            return KIcon(KPixmapSequence(QLatin1String("process-working"), 22).frameAt(0));
        case Tp::ConnectionStatusDisconnected:
            return KIcon(QLatin1String("user-offline"));
        default:
            return KIcon(QLatin1String("user-offline"));
        }
    } else {
        return KIcon();
    }
}

const QString AccountItem::connectionStatusReason() const
{
    if (!m_account->isEnabled()) {
        return i18n("Account disabled - Click checkbox to enable");
    }
    else if (m_account->connectionStatusReason() == Tp::ConnectionStatusReasonRequested) {
        return QString();
    }
    else {
        return KTp::ErrorDictionary::displayShortErrorMessage(m_account->connectionError());
    }
}

const QString AccountItem::connectionProtocolName() const
{
    return m_account->protocolName();
}

void AccountItem::generateIcon()
{
    QString iconPath = account()->iconName();

    //if the icon has not been set, we use the protocol icon
    if (iconPath.isEmpty()) {
        iconPath = QString::fromLatin1("im-%1").arg(account()->protocolName());
    }

    delete m_icon;
    if (m_account->isEnabled()) {
        m_icon = new KIcon(iconPath);
    } else {
        m_icon = new KIcon(KIconLoader::global()->loadIcon(iconPath, KIconLoader::Desktop, 32, KIconLoader::DisabledState));
    }

    if (!account()->isValid()) {
        //we paint a warning symbol in the right-bottom corner
        QPixmap pixmap = m_icon->pixmap(32, 32);
        QPainter painter(&pixmap);
        KIcon(QLatin1String("dialog-error")).paint(&painter, 15, 15, 16, 16);

        delete m_icon;
        m_icon = new KIcon(pixmap);
    }

    Q_EMIT(updated());
}

void AccountItem::onAccountRemoved(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "An error occurred removing the Account."
                 << op->errorName()
                 << op->errorMessage();
        return;
    }
}

void AccountItem::onTitleForCustomPages(QString mandatoryPage, QList<QString> optionalPage)
{
    Q_EMIT setTitleForCustomPages(mandatoryPage, optionalPage);
}

Tp::ConnectionStatus AccountItem::connectionStatus() const
{
    return m_account->connectionStatus();
}

#include "account-item.moc"
<|endoftext|>


<commit_before>// -*- c-style: gnu -*-

#include "act-gps-chart.h"

#include "act-config.h"
#include "act-format.h"

#include <math.h>

#define MILES_PER_METER 0.000621371192
#define FEET_PER_METER 3.2808399

#define SECS_PER_MILE(x) ((1. /  (x)) * (1. / MILES_PER_METER))
#define MILES_PER_SEC(x) (1. / ((x) * MILES_PER_METER))

#define MAX_TICKS 4
#define MIN_TICKS 2

namespace act {
namespace gps {

double
chart::line::convert_from_si(double x) const
{
  switch (conversion)
    {
    case value_conversion::IDENTITY:
      return x;
    case value_conversion::HEARTRATE_BPM_HRR: {
      const config &cfg = shared_config();
      return (x - cfg.resting_hr()) / (cfg.max_hr() - cfg.resting_hr()) * 100.; }
    case value_conversion::SPEED_MS_PACE:
      return x > 0 ? SECS_PER_MILE(x) : 0;
    case value_conversion::DISTANCE_M_MI:
      return x * MILES_PER_METER;
    case value_conversion::DISTANCE_M_FT:
      return x * FEET_PER_METER;
    default:
      return x;
    }
}

double
chart::line::convert_to_si(double x) const
{
  switch (conversion)
    {
    case value_conversion::IDENTITY:
      return x;
    case value_conversion::HEARTRATE_BPM_HRR: {
      const config &cfg = shared_config();
      return x * (1./100) * (cfg.max_hr() - cfg.resting_hr()) + cfg.resting_hr(); }
    case value_conversion::SPEED_MS_PACE:
      return x > 0 ? MILES_PER_SEC(x) : 0;
    case value_conversion::DISTANCE_M_MI:
      return x * (1. / MILES_PER_METER);
    case value_conversion::DISTANCE_M_FT:
      return x * (1. / FEET_PER_METER);
    default:
      return x;
    }
}

void
chart::line::update_values(const chart &c)
{
  const activity &a = c._activity;

  double mean, sdev;
  a.get_range(field, min_value, max_value, mean, sdev);

  double border = (max_value - min_value) * .05;
  min_value -= border;
  max_value += border;

  if (field == &activity::point::speed)
    {
      min_value = mean - 2.5 * sdev;
      max_value = mean + 2.5 * sdev;
    }
  else if (field == &activity::point::altitude)
    {
      if (max_value - min_value < 100)
	max_value = min_value + 100;
    }

  double range = max_value - min_value;
  scaled_min_value = min_value + range * min_ratio;
  scaled_max_value = min_value + range * max_ratio;

  tick_min = convert_from_si(min_value);
  tick_max = convert_from_si(max_value);

  if (tick_max < tick_min)
    std::swap(tick_min, tick_max);

  switch (conversion)
    {
    case value_conversion::HEARTRATE_BPM_HRR:
      tick_delta = 5;
      break;
    case value_conversion::SPEED_MS_PACE:
      tick_delta = 30;
      break;
    case value_conversion::DISTANCE_M_FT:
      tick_delta = 100;
      break;
    default:
      tick_delta = 1;
    }

  while ((tick_max - tick_min) / tick_delta > MAX_TICKS)
    tick_delta = tick_delta * 2;
  while ((tick_max - tick_min) / tick_delta < MIN_TICKS)
    tick_delta = tick_delta * .5;

  tick_min = floor(tick_min / tick_delta) * tick_delta;
  tick_max = ceil(tick_max / tick_delta) * tick_delta;
}

void
chart::line::format_tick(std::string &s, double tick, double value) const
{
  if (field == &activity::point::altitude)
    {
      format_distance(s, value, conversion == value_conversion::DISTANCE_M_FT
		      ? unit_type::feet : unit_type::metres);
    }
  else if (field == &activity::point::speed)
    {
      if (conversion == value_conversion::SPEED_MS_PACE)
	format_pace(s, value, unit_type::seconds_per_mile);
      else
	format_speed(s, value, unit_type::miles_per_hour);
    }
  else if (field == &activity::point::heart_rate)
    {
      format_number(s, tick);
      if (conversion == value_conversion::HEARTRATE_BPM_HRR)
	s.append(" %HRR");
      else
	s.append(" bpm");
    }
  else
    {
      format_number(s, tick);
    }
}

chart::chart(const activity &a, x_axis_type xa)
: _activity(a),
  _x_axis(xa),
  _x_axis_field(_x_axis == x_axis_type::DISTANCE
		? &activity::point::distance : &activity::point::time),
  _chart_rect(CGRectNull)
{
  double mean, sdev;
  a.get_range(_x_axis_field, _min_x_value, _max_x_value, mean, sdev);
}

void
chart::add_line(double activity::point:: *field, bool smoothed,
		value_conversion conv, line_color color,
		double min_ratio, double max_ratio)
{
  _lines.push_back(line(field, smoothed, conv, color, min_ratio, max_ratio));
}

void
chart::remove_all_lines()
{
  _lines.resize(0);
}

void
chart::update_values()
{
  for (size_t i = 0; i < _lines.size(); i++)
    _lines[i].update_values(*this);
}

void
chart::set_chart_rect(const CGRect &r)
{
  _chart_rect = r;
}

void
chart::draw(CGContextRef ctx)
{
  draw_background(ctx);

  for (size_t i = 0; i < _lines.size(); i++)
    draw_line(ctx, _lines[i]);

  draw_lap_markers(ctx);
}

void
chart::draw_background(CGContextRef ctx)
{
  CGContextSaveGState(ctx);
  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBFillColor(ctx, 0, 0, 0, 0.05);
  CGContextFillRect(ctx, _chart_rect);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.2);
  CGContextStrokeRect(ctx, CGRectInset(_chart_rect, .5, .5));
  CGContextRestoreGState(ctx);
}

void
chart::draw_line(CGContextRef ctx, const line &l)
{
  /* x' = (x - min_v) * v_scale * chart_w + chart_x
        = x * v_scale * chart_w - min_v * v_scale * chart_w + chart_x
	v_scale = 1 / (max_v - min_v). */

  CGFloat x_scale = 1. / (_max_x_value - _min_x_value);
  CGFloat x0 = (_chart_rect.origin.x
		- _min_x_value * x_scale * _chart_rect.size.width);
  CGFloat xm = x_scale * _chart_rect.size.width;

  CGFloat y_scale = 1. / (l.scaled_max_value - l.scaled_min_value);
  CGFloat y0 = (_chart_rect.origin.y
		- l.scaled_min_value * y_scale * _chart_rect.size.height);
  CGFloat ym = y_scale * _chart_rect.size.height;

  CGMutablePathRef path = CGPathCreateMutable();

  bool first_pt = true;
  CGFloat first_x = 0, first_y = 0;
  CGFloat last_x = 0, last_y = 0;

  // basic smoothing to avoid rendering multiple data points per pixel

  double skipped_total = 0, skipped_count = 0;

  for (size_t li = 0; li < _activity.laps().size(); li++)
    {
      const activity::lap &lap = _activity.laps()[li];
      const activity::point *track = &lap.track[0];

      for (size_t ti = 0; ti < lap.track.size(); ti++)
	{
	  const activity::point &p = track[ti];
	  double dist = p.*_x_axis_field;
	  double value = p.*(l.field);
	  if (dist == 0 || value == 0)
	    continue;
	  CGFloat x = dist * xm + x0;
	  if (first_pt || x - last_x >= 1)
	    {
	      if (skipped_count > 0)
		{
		  value = (value + skipped_total) / (skipped_count + 1);
		  skipped_total = skipped_count = 0;
		}
	      CGFloat y = value * ym + y0;
	      if (first_pt)
		{
		  CGPathMoveToPoint(path, 0, x, y);
		  first_x = x, first_y = y, first_pt = false;
		}
	      else
		CGPathAddLineToPoint(path, 0, x, y);
	      last_x = x, last_y = y;
	    }
	  else
	    skipped_total += value, skipped_count += 1;
	}
    }

  CGMutablePathRef fill_path = CGPathCreateMutableCopy(path);
  CGPathAddLineToPoint(fill_path, 0, last_x, _chart_rect.origin.y);
  CGPathAddLineToPoint(fill_path, 0, first_x, _chart_rect.origin.y);
  CGPathAddLineToPoint(fill_path, 0, first_x, first_y);
  CGPathCloseSubpath(fill_path);

  CGContextSaveGState(ctx);

  // Flip y axis so values grow upwards to match chart.

  CGContextTranslateCTM(ctx, _chart_rect.origin.x,
			_chart_rect.origin.y + _chart_rect.size.height);
  CGContextScaleCTM(ctx, 1, -1);
  CGContextTranslateCTM(ctx, -_chart_rect.origin.x, -_chart_rect.origin.y);

  // Fill gradient under the line

  CGContextSaveGState(ctx);

  switch (l.color)
    {
    case line_color::RED:
      CGContextSetRGBFillColor(ctx, 1, .5, .5, .4);
      break;
    case line_color::GREEN:
      CGContextSetRGBFillColor(ctx, .75, 1, .75, .4);
      break;
    case line_color::BLUE:
      CGContextSetRGBFillColor(ctx, .5, .75, 1, .4);
      break;
    case line_color::ORANGE:
      CGContextSetRGBFillColor(ctx, 1, .5, 0, .4);
      break;
    }

  CGContextAddPath(ctx, fill_path);
  CGContextFillPath(ctx);

  CGContextRestoreGState(ctx);

  // Draw data line

  CGContextSaveGState(ctx);

  switch (l.color)
    {
    case line_color::RED:
      CGContextSetRGBStrokeColor(ctx, 1, 0, 0.3, 1);
      break;
    case line_color::GREEN:
      CGContextSetRGBStrokeColor(ctx, 0, 0.8, 0.2, 1);
      break;
    case line_color::BLUE:
      CGContextSetRGBStrokeColor(ctx, 0, 0.2, 1, 1);
      break;
    case line_color::ORANGE:
      CGContextSetRGBStrokeColor(ctx, 1, 0.5, 0, 1);
      break;
    }

  CGContextAddPath(ctx, path);
  CGContextSetLineWidth(ctx, 1.5);
  CGContextStrokePath(ctx);

  CGContextRestoreGState(ctx);

  // Draw 'tick' lines at sensible points around the value's range.

  CGContextSaveGState(ctx);

  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.1);

  CGContextSelectFont(ctx, "Helvetica-Bold", 9, kCGEncodingMacRoman);
  CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
  CGContextSetTextDrawingMode(ctx, kCGTextFill);
  CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);

  for (double tick = l.tick_min; tick < l.tick_max; tick += l.tick_delta)
    {
      double value = l.convert_to_si(tick);
      CGFloat y = value;
      y = y * ym + y0;
      y = floor(y) + 0.5;
      CGPoint lines[2];
      lines[0] = CGPointMake(_chart_rect.origin.x, y);
      lines[1] = CGPointMake(_chart_rect.origin.x + _chart_rect.size.width, y);
      CGContextStrokeLineSegments(ctx, lines, 2);

      std::string s;
      l.format_tick(s, tick, value);

      CGContextShowTextAtPoint(ctx, _chart_rect.origin.x + 2,
			       y + 2, s.c_str(), s.size());
    }

  CGContextRestoreGState(ctx);

  CGContextRestoreGState(ctx);

  CGPathRelease(fill_path);
  CGPathRelease(path);
}

void
chart::draw_lap_markers(CGContextRef ctx)
{
  std::vector<CGPoint> lines;
  lines.reserve(2 * _activity.laps().size());

  CGFloat x_scale = 1. / (_max_x_value - _min_x_value);
  CGFloat x0 = (_chart_rect.origin.x
		- _min_x_value * x_scale * _chart_rect.size.width);
  CGFloat xm = x_scale * _chart_rect.size.width;

  CGFloat total_dist = _x_axis == x_axis_type::DISTANCE ? 0 : _activity.time();

  for (size_t i = 0; i < _activity.laps().size(); i++)
    {
      CGFloat x = total_dist * xm + x0;
      x = floor(x) + 0.5;
      lines.push_back(CGPointMake(x, _chart_rect.origin.y));
      lines.push_back(CGPointMake(x, _chart_rect.origin.y
				  + _chart_rect.size.height));
      if (_x_axis == x_axis_type::DISTANCE)
	total_dist += _activity.laps()[i].distance;
      else
	total_dist = _activity.laps()[i].time + _activity.laps()[i].duration;
    }

  CGContextSaveGState(ctx);
  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.1);
  CGContextStrokeLineSegments(ctx, &lines[0], lines.size());
  CGContextRestoreGState(ctx);
}

} // namespace gps
} // namespace act
<commit_msg>minor chart color change<commit_after>// -*- c-style: gnu -*-

#include "act-gps-chart.h"

#include "act-config.h"
#include "act-format.h"

#include <math.h>

#define MILES_PER_METER 0.000621371192
#define FEET_PER_METER 3.2808399

#define SECS_PER_MILE(x) ((1. /  (x)) * (1. / MILES_PER_METER))
#define MILES_PER_SEC(x) (1. / ((x) * MILES_PER_METER))

#define MAX_TICKS 4
#define MIN_TICKS 2

namespace act {
namespace gps {

double
chart::line::convert_from_si(double x) const
{
  switch (conversion)
    {
    case value_conversion::IDENTITY:
      return x;
    case value_conversion::HEARTRATE_BPM_HRR: {
      const config &cfg = shared_config();
      return (x - cfg.resting_hr()) / (cfg.max_hr() - cfg.resting_hr()) * 100.; }
    case value_conversion::SPEED_MS_PACE:
      return x > 0 ? SECS_PER_MILE(x) : 0;
    case value_conversion::DISTANCE_M_MI:
      return x * MILES_PER_METER;
    case value_conversion::DISTANCE_M_FT:
      return x * FEET_PER_METER;
    default:
      return x;
    }
}

double
chart::line::convert_to_si(double x) const
{
  switch (conversion)
    {
    case value_conversion::IDENTITY:
      return x;
    case value_conversion::HEARTRATE_BPM_HRR: {
      const config &cfg = shared_config();
      return x * (1./100) * (cfg.max_hr() - cfg.resting_hr()) + cfg.resting_hr(); }
    case value_conversion::SPEED_MS_PACE:
      return x > 0 ? MILES_PER_SEC(x) : 0;
    case value_conversion::DISTANCE_M_MI:
      return x * (1. / MILES_PER_METER);
    case value_conversion::DISTANCE_M_FT:
      return x * (1. / FEET_PER_METER);
    default:
      return x;
    }
}

void
chart::line::update_values(const chart &c)
{
  const activity &a = c._activity;

  double mean, sdev;
  a.get_range(field, min_value, max_value, mean, sdev);

  double border = (max_value - min_value) * .05;
  min_value -= border;
  max_value += border;

  if (field == &activity::point::speed)
    {
      min_value = mean - 2.5 * sdev;
      max_value = mean + 2.5 * sdev;
    }
  else if (field == &activity::point::altitude)
    {
      if (max_value - min_value < 100)
	max_value = min_value + 100;
    }

  double range = max_value - min_value;
  scaled_min_value = min_value + range * min_ratio;
  scaled_max_value = min_value + range * max_ratio;

  tick_min = convert_from_si(min_value);
  tick_max = convert_from_si(max_value);

  if (tick_max < tick_min)
    std::swap(tick_min, tick_max);

  switch (conversion)
    {
    case value_conversion::HEARTRATE_BPM_HRR:
      tick_delta = 5;
      break;
    case value_conversion::SPEED_MS_PACE:
      tick_delta = 30;
      break;
    case value_conversion::DISTANCE_M_FT:
      tick_delta = 100;
      break;
    default:
      tick_delta = 1;
    }

  while ((tick_max - tick_min) / tick_delta > MAX_TICKS)
    tick_delta = tick_delta * 2;
  while ((tick_max - tick_min) / tick_delta < MIN_TICKS)
    tick_delta = tick_delta * .5;

  tick_min = floor(tick_min / tick_delta) * tick_delta;
  tick_max = ceil(tick_max / tick_delta) * tick_delta;
}

void
chart::line::format_tick(std::string &s, double tick, double value) const
{
  if (field == &activity::point::altitude)
    {
      format_distance(s, value, conversion == value_conversion::DISTANCE_M_FT
		      ? unit_type::feet : unit_type::metres);
    }
  else if (field == &activity::point::speed)
    {
      if (conversion == value_conversion::SPEED_MS_PACE)
	format_pace(s, value, unit_type::seconds_per_mile);
      else
	format_speed(s, value, unit_type::miles_per_hour);
    }
  else if (field == &activity::point::heart_rate)
    {
      format_number(s, tick);
      if (conversion == value_conversion::HEARTRATE_BPM_HRR)
	s.append(" %HRR");
      else
	s.append(" bpm");
    }
  else
    {
      format_number(s, tick);
    }
}

chart::chart(const activity &a, x_axis_type xa)
: _activity(a),
  _x_axis(xa),
  _x_axis_field(_x_axis == x_axis_type::DISTANCE
		? &activity::point::distance : &activity::point::time),
  _chart_rect(CGRectNull)
{
  double mean, sdev;
  a.get_range(_x_axis_field, _min_x_value, _max_x_value, mean, sdev);
}

void
chart::add_line(double activity::point:: *field, bool smoothed,
		value_conversion conv, line_color color,
		double min_ratio, double max_ratio)
{
  _lines.push_back(line(field, smoothed, conv, color, min_ratio, max_ratio));
}

void
chart::remove_all_lines()
{
  _lines.resize(0);
}

void
chart::update_values()
{
  for (size_t i = 0; i < _lines.size(); i++)
    _lines[i].update_values(*this);
}

void
chart::set_chart_rect(const CGRect &r)
{
  _chart_rect = r;
}

void
chart::draw(CGContextRef ctx)
{
  draw_background(ctx);

  for (size_t i = 0; i < _lines.size(); i++)
    draw_line(ctx, _lines[i]);

  draw_lap_markers(ctx);
}

void
chart::draw_background(CGContextRef ctx)
{
  CGContextSaveGState(ctx);
  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBFillColor(ctx, 0, 0, 0, 0.05);
  CGContextFillRect(ctx, _chart_rect);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.2);
  CGContextStrokeRect(ctx, CGRectInset(_chart_rect, .5, .5));
  CGContextRestoreGState(ctx);
}

void
chart::draw_line(CGContextRef ctx, const line &l)
{
  /* x' = (x - min_v) * v_scale * chart_w + chart_x
        = x * v_scale * chart_w - min_v * v_scale * chart_w + chart_x
	v_scale = 1 / (max_v - min_v). */

  CGFloat x_scale = 1. / (_max_x_value - _min_x_value);
  CGFloat x0 = (_chart_rect.origin.x
		- _min_x_value * x_scale * _chart_rect.size.width);
  CGFloat xm = x_scale * _chart_rect.size.width;

  CGFloat y_scale = 1. / (l.scaled_max_value - l.scaled_min_value);
  CGFloat y0 = (_chart_rect.origin.y
		- l.scaled_min_value * y_scale * _chart_rect.size.height);
  CGFloat ym = y_scale * _chart_rect.size.height;

  CGMutablePathRef path = CGPathCreateMutable();

  bool first_pt = true;
  CGFloat first_x = 0, first_y = 0;
  CGFloat last_x = 0, last_y = 0;

  // basic smoothing to avoid rendering multiple data points per pixel

  double skipped_total = 0, skipped_count = 0;

  for (size_t li = 0; li < _activity.laps().size(); li++)
    {
      const activity::lap &lap = _activity.laps()[li];
      const activity::point *track = &lap.track[0];

      for (size_t ti = 0; ti < lap.track.size(); ti++)
	{
	  const activity::point &p = track[ti];
	  double dist = p.*_x_axis_field;
	  double value = p.*(l.field);
	  if (dist == 0 || value == 0)
	    continue;
	  CGFloat x = dist * xm + x0;
	  if (first_pt || x - last_x >= 1)
	    {
	      if (skipped_count > 0)
		{
		  value = (value + skipped_total) / (skipped_count + 1);
		  skipped_total = skipped_count = 0;
		}
	      CGFloat y = value * ym + y0;
	      if (first_pt)
		{
		  CGPathMoveToPoint(path, 0, x, y);
		  first_x = x, first_y = y, first_pt = false;
		}
	      else
		CGPathAddLineToPoint(path, 0, x, y);
	      last_x = x, last_y = y;
	    }
	  else
	    skipped_total += value, skipped_count += 1;
	}
    }

  CGMutablePathRef fill_path = CGPathCreateMutableCopy(path);
  CGPathAddLineToPoint(fill_path, 0, last_x, _chart_rect.origin.y);
  CGPathAddLineToPoint(fill_path, 0, first_x, _chart_rect.origin.y);
  CGPathAddLineToPoint(fill_path, 0, first_x, first_y);
  CGPathCloseSubpath(fill_path);

  CGContextSaveGState(ctx);

  // Flip y axis so values grow upwards to match chart.

  CGContextTranslateCTM(ctx, _chart_rect.origin.x,
			_chart_rect.origin.y + _chart_rect.size.height);
  CGContextScaleCTM(ctx, 1, -1);
  CGContextTranslateCTM(ctx, -_chart_rect.origin.x, -_chart_rect.origin.y);

  // Fill gradient under the line

  CGContextSaveGState(ctx);

  switch (l.color)
    {
    case line_color::RED:
      CGContextSetRGBFillColor(ctx, 1, .5, .5, .4);
      break;
    case line_color::GREEN:
      CGContextSetRGBFillColor(ctx, .75, 1, .75, .4);
      break;
    case line_color::BLUE:
      CGContextSetRGBFillColor(ctx, .5, .75, 1, .4);
      break;
    case line_color::ORANGE:
      CGContextSetRGBFillColor(ctx, 1, .5, 0, .4);
      break;
    }

  CGContextAddPath(ctx, fill_path);
  CGContextFillPath(ctx);

  CGContextRestoreGState(ctx);

  // Draw data line

  CGContextSaveGState(ctx);

  switch (l.color)
    {
    case line_color::RED:
      CGContextSetRGBStrokeColor(ctx, 1, 0, 0.3, 1);
      break;
    case line_color::GREEN:
      CGContextSetRGBStrokeColor(ctx, 0, 0.6, 0.2, 1);
      break;
    case line_color::BLUE:
      CGContextSetRGBStrokeColor(ctx, 0, 0.2, 1, 1);
      break;
    case line_color::ORANGE:
      CGContextSetRGBStrokeColor(ctx, 1, 0.5, 0, 1);
      break;
    }

  CGContextAddPath(ctx, path);
  CGContextSetLineWidth(ctx, 1.5);
  CGContextStrokePath(ctx);

  CGContextRestoreGState(ctx);

  // Draw 'tick' lines at sensible points around the value's range.

  CGContextSaveGState(ctx);

  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.1);

  CGContextSelectFont(ctx, "Helvetica-Bold", 9, kCGEncodingMacRoman);
  CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
  CGContextSetTextDrawingMode(ctx, kCGTextFill);
  CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);

  for (double tick = l.tick_min; tick < l.tick_max; tick += l.tick_delta)
    {
      double value = l.convert_to_si(tick);
      CGFloat y = value;
      y = y * ym + y0;
      y = floor(y) + 0.5;
      CGPoint lines[2];
      lines[0] = CGPointMake(_chart_rect.origin.x, y);
      lines[1] = CGPointMake(_chart_rect.origin.x + _chart_rect.size.width, y);
      CGContextStrokeLineSegments(ctx, lines, 2);

      std::string s;
      l.format_tick(s, tick, value);

      CGContextShowTextAtPoint(ctx, _chart_rect.origin.x + 2,
			       y + 2, s.c_str(), s.size());
    }

  CGContextRestoreGState(ctx);

  CGContextRestoreGState(ctx);

  CGPathRelease(fill_path);
  CGPathRelease(path);
}

void
chart::draw_lap_markers(CGContextRef ctx)
{
  std::vector<CGPoint> lines;
  lines.reserve(2 * _activity.laps().size());

  CGFloat x_scale = 1. / (_max_x_value - _min_x_value);
  CGFloat x0 = (_chart_rect.origin.x
		- _min_x_value * x_scale * _chart_rect.size.width);
  CGFloat xm = x_scale * _chart_rect.size.width;

  CGFloat total_dist = _x_axis == x_axis_type::DISTANCE ? 0 : _activity.time();

  for (size_t i = 0; i < _activity.laps().size(); i++)
    {
      CGFloat x = total_dist * xm + x0;
      x = floor(x) + 0.5;
      lines.push_back(CGPointMake(x, _chart_rect.origin.y));
      lines.push_back(CGPointMake(x, _chart_rect.origin.y
				  + _chart_rect.size.height));
      if (_x_axis == x_axis_type::DISTANCE)
	total_dist += _activity.laps()[i].distance;
      else
	total_dist = _activity.laps()[i].time + _activity.laps()[i].duration;
    }

  CGContextSaveGState(ctx);
  CGContextSetLineWidth(ctx, 1);
  CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0.1);
  CGContextStrokeLineSegments(ctx, &lines[0], lines.size());
  CGContextRestoreGState(ctx);
}

} // namespace gps
} // namespace act
<|endoftext|>