<commit_before>#include "geometria/SuperficieBezier.h"
#include <iostream>

SuperficieBezier::SuperficieBezier() :
		Superficie() {
}

SuperficieBezier::SuperficieBezier(const SuperficieBezier& superficie) :
		Superficie(superficie) {
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = superficie.pontos[i][j];
		}
	}
	this->pontosParametricos = superficie.pontosParametricos;
}

SuperficieBezier::SuperficieBezier(const String& nome,
		const QList<Ponto>& pontos, const QColor& cor) :
		Superficie(nome, Tipo::SUPERFICIE_BEZIER, cor) {
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = pontos.at(i * 4 + j);
		}
	}
	this->calcularPontosParametricos();
}

SuperficieBezier::~SuperficieBezier() {
}

SuperficieBezier& SuperficieBezier::operator=(
		const SuperficieBezier& superficie) {
	this->Superficie::operator =(superficie);
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = superficie.pontos[i][j];
		}
	}
	this->pontosParametricos = superficie.pontosParametricos;
	return *this;
}

ObjetoGeometrico* SuperficieBezier::clonar() const {
	return new SuperficieBezier(*this);
}

QList<Ponto> SuperficieBezier::getPontos() const {
	QList<Ponto> pontos;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			pontos.insert(i * 4 + j, this->pontos[i][j]);
		}
	}
	return pontos;
}

QList<Ponto*> SuperficieBezier::getPontosObjeto() {
	QList<Ponto*> pontos;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			pontos.insert(i * 4 + j, &this->pontos[i][j]);
		}
	}
	return pontos;
}

const String SuperficieBezier::toString() const {
	String r = "[";
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			r += this->pontos[i][j].toString();
			if (i != 4 && j != 4)
				r += ", ";
		}
	}
	r += "]";
	return r;
}

QList<QList<Ponto>> SuperficieBezier::getPontosParametricos() const {
	for (int i = 0; i < pontosParametricos.size(); i++) {
		for (int j = 0; j < pontosParametricos.at(i).size(); j++) {
			std::cout << pontosParametricos.at(i).at(j).toString() << std::endl;
		}
	}
	return this->pontosParametricos;
}

void SuperficieBezier::calcularPontosParametricos(const double t) {
	double** x = new double*[4];
	double** y = new double*[4];
	double** z = new double*[4];

	for (int i = 0; i < 4; i++) {
		x[i] = new double[4];
		y[i] = new double[4];
		z[i] = new double[4];

		for (int j = 0; j < 4; j++) {
			x[i][j] = pontos[i][j].getX();
			y[i][j] = pontos[i][j].getY();
			z[i][j] = pontos[i][j].getZ();
		}
	}
	pontosParametricos.clear();

	//calcular matrizes de coeficientes
	double** bezier = new double*[4];
	double** coeficientesX = new double*[4];
	double** coeficientesY = new double*[4];
	double** coeficientesZ = new double*[4];
	double** buffer = new double*[4];

	for (int i = 0; i < 4; i++) {
		bezier[i] = new double[4];
		coeficientesX[i] = new double[4];
		coeficientesY[i] = new double[4];
		coeficientesZ[i] = new double[4];
		buffer[i] = new double[4];
	}

	bezier[0][0] = -1; bezier[0][1] = 3; bezier[0][2] = -3; bezier[0][3] = 1;
	bezier[1][0] = 3; bezier[1][1] = -6; bezier[1][2] = 3; bezier[1][3] = 0;
	bezier[2][0] = -3; bezier[2][1] = 3; bezier[2][2] = 0; bezier[2][3] = 0;
	bezier[3][0] = 1; bezier[3][1] = 0; bezier[3][2] = 0; bezier[3][3] = 0;

	this->multiplicarMatrizes(bezier, x, buffer);
	this->multiplicarMatrizes(buffer, bezier, coeficientesX);
	this->multiplicarMatrizes(bezier, y, buffer);
	this->multiplicarMatrizes(buffer, bezier, coeficientesY);
	this->multiplicarMatrizes(bezier, z, buffer);
	this->multiplicarMatrizes(buffer, bezier, coeficientesZ);

	double** ds = new double*[4];
	double** dt = new double*[4];
	double** fwdX = new double*[4];
	double** fwdY = new double*[4];
	double** fwdZ = new double*[4];

	for (int i = 0; i < 4; i++) {
		ds[i] = new double[4];
		dt[i] = new double[4];
		fwdX[i] = new double[4];
		fwdY[i] = new double[4];
		fwdZ[i] = new double[4];
	}

	//calcular matrizes de forward differences
	dt[0][0] = 0; dt[0][1] = t * t * t; dt[0][2] = 6 * t * t * t; dt[0][3] = 6 * t * t * t;
	dt[1][0] = 0; dt[1][1] = t * t; dt[1][2] = 2 * t * t; dt[1][3] = 0;
	dt[2][0] = 0; dt[2][1] = t; dt[2][2] = 0; dt[2][3] = 0;
	dt[3][0] = 1; dt[3][1] = 0; dt[3][2] = 0; dt[3][3] = 0;

	ds[0][0] = 0; ds[0][1] = 0; ds[0][2] = 0; ds[0][3] = 1;
	ds[1][0] = t * t * t; ds[1][1] = t * t; ds[1][2] = t; ds[1][3] = 0;
	ds[2][0] = 6 * t * t * t; ds[2][1] = 2 * t * t; ds[2][2] = 0; ds[2][3] = 0;
	ds[3][0] = 6 * t * t * t; ds[3][1] = 0; ds[3][2] = 0; ds[3][3] = 0;

	this->multiplicarMatrizes(ds, coeficientesX, buffer);
	this->multiplicarMatrizes(buffer, dt, fwdX);
	this->multiplicarMatrizes(ds, coeficientesY, buffer);
	this->multiplicarMatrizes(buffer, dt, fwdY);
	this->multiplicarMatrizes(ds, coeficientesZ, buffer);
	this->multiplicarMatrizes(buffer, dt, fwdZ);

	//duplica e transpõe forward differences
	double fwdXs[4][4];
	double fwdYs[4][4];
	double fwdZs[4][4];
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			fwdXs[j][i] = fwdX[i][j];
			fwdYs[j][i] = fwdY[i][j];
			fwdZs[j][i] = fwdZ[i][j];
		}
	}

	//desenha curvas no sentido de t
	for (double i = 0; i < 1; i += t) {
		pontosParametricos.append(
				this->geraCurva(fwdX[0], fwdY[0], fwdZ[0], t));
		//atualiza forward differences
		for (int a = 0; a < 3; a++) {
			for (int b = 0; b < 4; b++) {
				fwdX[a][b] += fwdX[a + 1][b];
				fwdY[a][b] += fwdY[a + 1][b];
				fwdZ[a][b] += fwdZ[a + 1][b];
			}
		}
	}

	//desenha curvas no sentido de s
	for (double i = 0; i < 1; i += t) {
		pontosParametricos.append(
				this->geraCurva(fwdXs[0], fwdYs[0], fwdZs[0], t));
		//atualiza forward differences
		for (int a = 0; a < 3; a++) {
			for (int b = 0; b < 4; b++) {
				fwdXs[a][b] += fwdXs[a + 1][b];
				fwdYs[a][b] += fwdYs[a + 1][b];
				fwdZs[a][b] += fwdZs[a + 1][b];
			}
		}
	}

	for (int i = 0; i < 4; i++) {
		delete bezier[i];
		delete coeficientesX[i];
		delete coeficientesY[i];
		delete coeficientesZ[i];
		delete ds[i];
		delete dt[i];
		delete fwdX[i];
		delete fwdY[i];
		delete fwdZ[i];
		delete buffer[i];
	}

	delete bezier;
	delete coeficientesX;
	delete coeficientesY;
	delete coeficientesZ;
	delete ds;
	delete dt;
	delete fwdX;
	delete fwdY;
	delete fwdZ;
	delete buffer;
}

void SuperficieBezier::multiplicarMatrizes(double** mat1, double** mat2,
		double** resultado) {
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			resultado[i][j] = 0;
		}
	}
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				resultado[i][j] += mat1[i][k] * mat2[k][j];
			}
		}
	}
}

QList<Ponto> SuperficieBezier::geraCurva(double x[4], double y[4], double z[4],
		double t) {
	QList<Ponto> pontos;
	pontos.append(Ponto("", x[0], y[0], z[0]));
	for (double i = 0; i < 1; i += t) {
		for (int j = 0; j < 3; j++) {
			x[j] += x[j + 1];
			y[j] += y[j + 1];
			z[j] += z[j + 1];
		}
		pontos.append(Ponto("", x[0], y[0], z[0]));
	}
	return pontos;
}
<commit_msg>Buffer de matrizes corrigido.<commit_after>#include "geometria/SuperficieBezier.h"
#include <iostream>

SuperficieBezier::SuperficieBezier() :
		Superficie() {
}

SuperficieBezier::SuperficieBezier(const SuperficieBezier& superficie) :
		Superficie(superficie) {
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = superficie.pontos[i][j];
		}
	}
	this->pontosParametricos = superficie.pontosParametricos;
}

SuperficieBezier::SuperficieBezier(const String& nome,
		const QList<Ponto>& pontos, const QColor& cor) :
		Superficie(nome, Tipo::SUPERFICIE_BEZIER, cor) {
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = pontos.at(i * 4 + j);
		}
	}
	this->calcularPontosParametricos();
}

SuperficieBezier::~SuperficieBezier() {
}

SuperficieBezier& SuperficieBezier::operator=(
		const SuperficieBezier& superficie) {
	this->Superficie::operator =(superficie);
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			this->pontos[i][j] = superficie.pontos[i][j];
		}
	}
	this->pontosParametricos = superficie.pontosParametricos;
	return *this;
}

ObjetoGeometrico* SuperficieBezier::clonar() const {
	return new SuperficieBezier(*this);
}

QList<Ponto> SuperficieBezier::getPontos() const {
	QList<Ponto> pontos;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			pontos.insert(i * 4 + j, this->pontos[i][j]);
		}
	}
	return pontos;
}

QList<Ponto*> SuperficieBezier::getPontosObjeto() {
	QList<Ponto*> pontos;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			pontos.insert(i * 4 + j, &this->pontos[i][j]);
		}
	}
	return pontos;
}

const String SuperficieBezier::toString() const {
	String r = "[";
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			r += this->pontos[i][j].toString();
			if (i != 4 && j != 4)
				r += ", ";
		}
	}
	r += "]";
	return r;
}

QList<QList<Ponto>> SuperficieBezier::getPontosParametricos() const {
	for (int i = 0; i < pontosParametricos.size(); i++) {
		for (int j = 0; j < pontosParametricos.at(i).size(); j++) {
			std::cout << pontosParametricos.at(i).at(j).toString() << std::endl;
		}
	}
	return this->pontosParametricos;
}

void SuperficieBezier::calcularPontosParametricos(const double t) {
	double** x = new double*[4];
	double** y = new double*[4];
	double** z = new double*[4];

	for (int i = 0; i < 4; i++) {
		x[i] = new double[4];
		y[i] = new double[4];
		z[i] = new double[4];

		for (int j = 0; j < 4; j++) {
			x[i][j] = pontos[i][j].getX();
			y[i][j] = pontos[i][j].getY();
			z[i][j] = pontos[i][j].getZ();
		}
	}
	pontosParametricos.clear();

	//calcular matrizes de coeficientes
	double** bezier = new double*[4];
	double** coeficientesX = new double*[4];
	double** coeficientesY = new double*[4];
	double** coeficientesZ = new double*[4];

	for (int i = 0; i < 4; i++) {
		bezier[i] = new double[4];
		coeficientesX[i] = new double[4];
		coeficientesY[i] = new double[4];
		coeficientesZ[i] = new double[4];
	}

	bezier[0][0] = -1; bezier[0][1] = 3; bezier[0][2] = -3; bezier[0][3] = 1;
	bezier[1][0] = 3; bezier[1][1] = -6; bezier[1][2] = 3; bezier[1][3] = 0;
	bezier[2][0] = -3; bezier[2][1] = 3; bezier[2][2] = 0; bezier[2][3] = 0;
	bezier[3][0] = 1; bezier[3][1] = 0; bezier[3][2] = 0; bezier[3][3] = 0;

	this->multiplicarMatrizes(bezier, x, coeficientesX);
	this->multiplicarMatrizes(coeficientesX, bezier, coeficientesX);
	this->multiplicarMatrizes(bezier, y, coeficientesY);
	this->multiplicarMatrizes(coeficientesY, bezier, coeficientesY);
	this->multiplicarMatrizes(bezier, z, coeficientesZ);
	this->multiplicarMatrizes(coeficientesZ, bezier, coeficientesZ);

	double** ds = new double*[4];
	double** dt = new double*[4];
	double** fwdX = new double*[4];
	double** fwdY = new double*[4];
	double** fwdZ = new double*[4];

	for (int i = 0; i < 4; i++) {
		ds[i] = new double[4];
		dt[i] = new double[4];
		fwdX[i] = new double[4];
		fwdY[i] = new double[4];
		fwdZ[i] = new double[4];
	}

	//calcular matrizes de forward differences
	dt[0][0] = 0; dt[0][1] = t * t * t; dt[0][2] = 6 * t * t * t; dt[0][3] = 6 * t * t * t;
	dt[1][0] = 0; dt[1][1] = t * t; dt[1][2] = 2 * t * t; dt[1][3] = 0;
	dt[2][0] = 0; dt[2][1] = t; dt[2][2] = 0; dt[2][3] = 0;
	dt[3][0] = 1; dt[3][1] = 0; dt[3][2] = 0; dt[3][3] = 0;

	ds[0][0] = 0; ds[0][1] = 0; ds[0][2] = 0; ds[0][3] = 1;
	ds[1][0] = t * t * t; ds[1][1] = t * t; ds[1][2] = t; ds[1][3] = 0;
	ds[2][0] = 6 * t * t * t; ds[2][1] = 2 * t * t; ds[2][2] = 0; ds[2][3] = 0;
	ds[3][0] = 6 * t * t * t; ds[3][1] = 0; ds[3][2] = 0; ds[3][3] = 0;

	this->multiplicarMatrizes(ds, coeficientesX, coeficientesX);
	this->multiplicarMatrizes(coeficientesX, dt, fwdX);
	this->multiplicarMatrizes(ds, coeficientesY, coeficientesY);
	this->multiplicarMatrizes(coeficientesY, dt, fwdY);
	this->multiplicarMatrizes(ds, coeficientesZ, coeficientesZ);
	this->multiplicarMatrizes(coeficientesZ, dt, fwdZ);

	//duplica e transpõe forward differences
	double fwdXs[4][4];
	double fwdYs[4][4];
	double fwdZs[4][4];
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			fwdXs[j][i] = fwdX[i][j];
			fwdYs[j][i] = fwdY[i][j];
			fwdZs[j][i] = fwdZ[i][j];
		}
	}

	//desenha curvas no sentido de t
	for (double i = 0; i < 1; i += t) {
		pontosParametricos.append(
				this->geraCurva(fwdX[0], fwdY[0], fwdZ[0], t));
		//atualiza forward differences
		for (int a = 0; a < 3; a++) {
			for (int b = 0; b < 4; b++) {
				fwdX[a][b] += fwdX[a + 1][b];
				fwdY[a][b] += fwdY[a + 1][b];
				fwdZ[a][b] += fwdZ[a + 1][b];
			}
		}
	}

	//desenha curvas no sentido de s
	for (double i = 0; i < 1; i += t) {
		pontosParametricos.append(
				this->geraCurva(fwdXs[0], fwdYs[0], fwdZs[0], t));
		//atualiza forward differences
		for (int a = 0; a < 3; a++) {
			for (int b = 0; b < 4; b++) {
				fwdXs[a][b] += fwdXs[a + 1][b];
				fwdYs[a][b] += fwdYs[a + 1][b];
				fwdZs[a][b] += fwdZs[a + 1][b];
			}
		}
	}

	for (int i = 0; i < 4; i++) {
		delete bezier[i];
		delete coeficientesX[i];
		delete coeficientesY[i];
		delete coeficientesZ[i];
		delete ds[i];
		delete dt[i];
		delete fwdX[i];
		delete fwdY[i];
		delete fwdZ[i];
	}

	delete bezier;
	delete coeficientesX;
	delete coeficientesY;
	delete coeficientesZ;
	delete ds;
	delete dt;
	delete fwdX;
	delete fwdY;
	delete fwdZ;
}

void SuperficieBezier::multiplicarMatrizes(double** mat1, double** mat2,
		double** resultado) {
	double buffer[4][4];

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				buffer[i][j] += mat1[i][k] * mat2[k][j];
			}
		}
	}

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			resultado[i][j] = buffer[i][j];
		}
	}
}

QList<Ponto> SuperficieBezier::geraCurva(double x[4], double y[4], double z[4],
		double t) {
	QList<Ponto> pontos;
	pontos.append(Ponto("", x[0], y[0], z[0]));
	for (double i = 0; i < 1; i += t) {
		for (int j = 0; j < 3; j++) {
			x[j] += x[j + 1];
			y[j] += y[j + 1];
			z[j] += z[j + 1];
		}
		pontos.append(Ponto("", x[0], y[0], z[0]));
	}
	return pontos;
}
<|endoftext|>


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

#include "precomp.hpp"
#include "kdtree.hpp"

/****************************************************************************************\
*                              K-Nearest Neighbors Classifier                            *
\****************************************************************************************/

namespace cv {
namespace ml {

const String NAME_BRUTE_FORCE = "opencv_ml_knn";
const String NAME_KDTREE = "opencv_ml_knn_kd";

class Impl
{
public:
    Impl()
    {
        defaultK = 10;
        isclassifier = true;
        Emax = INT_MAX;
    }

    virtual ~Impl() {}
    virtual String getModelName() const = 0;
    virtual int getType() const = 0;
    virtual float findNearest( InputArray _samples, int k,
                               OutputArray _results,
                               OutputArray _neighborResponses,
                               OutputArray _dists ) const = 0;

    bool train( const Ptr<TrainData>& data, int flags )
    {
        Mat new_samples = data->getTrainSamples(ROW_SAMPLE);
        Mat new_responses;
        data->getTrainResponses().convertTo(new_responses, CV_32F);
        bool update = (flags & ml::KNearest::UPDATE_MODEL) != 0 && !samples.empty();

        CV_Assert( new_samples.type() == CV_32F );

        if( !update )
        {
            clear();
        }
        else
        {
            CV_Assert( new_samples.cols == samples.cols &&
                       new_responses.cols == responses.cols );
        }

        samples.push_back(new_samples);
        responses.push_back(new_responses);

        doTrain(samples);

        return true;
    }

    virtual void doTrain(InputArray points) { (void)points; }

    void clear()
    {
        samples.release();
        responses.release();
    }

    void read( const FileNode& fn )
    {
        clear();
        isclassifier = (int)fn["is_classifier"] != 0;
        defaultK = (int)fn["default_k"];

        fn["samples"] >> samples;
        fn["responses"] >> responses;
    }

    void write( FileStorage& fs ) const
    {
        fs << "is_classifier" << (int)isclassifier;
        fs << "default_k" << defaultK;

        fs << "samples" << samples;
        fs << "responses" << responses;
    }

public:
    int defaultK;
    bool isclassifier;
    int Emax;

    Mat samples;
    Mat responses;
};

class BruteForceImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_BRUTE_FORCE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::BRUTE_FORCE; }

    void findNearestCore( const Mat& _samples, int k0, const Range& range,
                          Mat* results, Mat* neighbor_responses,
                          Mat* dists, float* presult ) const
    {
        int testidx, baseidx, i, j, d = samples.cols, nsamples = samples.rows;
        int testcount = range.end - range.start;
        int k = std::min(k0, nsamples);

        AutoBuffer<float> buf(testcount*k*2);
        float* dbuf = buf;
        float* rbuf = dbuf + testcount*k;

        const float* rptr = responses.ptr<float>();

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            for( i = 0; i < k; i++ )
            {
                dbuf[testidx*k + i] = FLT_MAX;
                rbuf[testidx*k + i] = 0.f;
            }
        }

        for( baseidx = 0; baseidx < nsamples; baseidx++ )
        {
            for( testidx = 0; testidx < testcount; testidx++ )
            {
                const float* v = samples.ptr<float>(baseidx);
                const float* u = _samples.ptr<float>(testidx + range.start);

                float s = 0;
                for( i = 0; i <= d - 4; i += 4 )
                {
                    float t0 = u[i] - v[i], t1 = u[i+1] - v[i+1];
                    float t2 = u[i+2] - v[i+2], t3 = u[i+3] - v[i+3];
                    s += t0*t0 + t1*t1 + t2*t2 + t3*t3;
                }

                for( ; i < d; i++ )
                {
                    float t0 = u[i] - v[i];
                    s += t0*t0;
                }

                Cv32suf si;
                si.f = (float)s;
                Cv32suf* dd = (Cv32suf*)(&dbuf[testidx*k]);
                float* nr = &rbuf[testidx*k];

                for( i = k; i > 0; i-- )
                    if( si.i >= dd[i-1].i )
                        break;
                if( i >= k )
                    continue;

                for( j = k-2; j >= i; j-- )
                {
                    dd[j+1].i = dd[j].i;
                    nr[j+1] = nr[j];
                }
                dd[i].i = si.i;
                nr[i] = rptr[baseidx];
            }
        }

        float result = 0.f;
        float inv_scale = 1.f/k;

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            if( neighbor_responses )
            {
                float* nr = neighbor_responses->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    nr[j] = rbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    nr[j] = 0.f;
            }

            if( dists )
            {
                float* dptr = dists->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    dptr[j] = dbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    dptr[j] = 0.f;
            }

            if( results || testidx+range.start == 0 )
            {
                if( !isclassifier || k == 1 )
                {
                    float s = 0.f;
                    for( j = 0; j < k; j++ )
                        s += rbuf[testidx*k + j];
                    result = (float)(s*inv_scale);
                }
                else
                {
                    float* rp = rbuf + testidx*k;
                    std::sort(rp, rp+k);

                    result = rp[0];
                    int prev_start = 0;
                    int best_count = 0;
                    for( j = 1; j <= k; j++ )
                    {
                        if( j == k || rp[j] != rp[j-1] )
                        {
                            int count = j - prev_start;
                            if( best_count < count )
                            {
                                best_count = count;
                                result = rp[j-1];
                            }
                            prev_start = j;
                        }
                    }
                }
                if( results )
                    results->at<float>(testidx + range.start) = result;
                if( presult && testidx+range.start == 0 )
                    *presult = result;
            }
        }
    }

    struct findKNearestInvoker : public ParallelLoopBody
    {
        findKNearestInvoker(const BruteForceImpl* _p, int _k, const Mat& __samples,
                            Mat* __results, Mat* __neighbor_responses, Mat* __dists, float* _presult)
        {
            p = _p;
            k = _k;
            _samples = &__samples;
            _results = __results;
            _neighbor_responses = __neighbor_responses;
            _dists = __dists;
            presult = _presult;
        }

        void operator()(const Range& range) const CV_OVERRIDE
        {
            int delta = std::min(range.end - range.start, 256);
            for( int start = range.start; start < range.end; start += delta )
            {
                p->findNearestCore( *_samples, k, Range(start, std::min(start + delta, range.end)),
                                    _results, _neighbor_responses, _dists, presult );
            }
        }

        const BruteForceImpl* p;
        int k;
        const Mat* _samples;
        Mat* _results;
        Mat* _neighbor_responses;
        Mat* _dists;
        float* presult;
    };

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d, *pres = 0, *pnr = 0, *pd = 0;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            pres = &(res = _results.getMat());
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            pnr = &(nr = _neighborResponses.getMat());
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            pd = &(d = _dists.getMat());
        }

        findKNearestInvoker invoker(this, k, test_samples, pres, pnr, pd, &result);
        parallel_for_(Range(0, testcount), invoker);
        //invoker(Range(0, testcount));
        return result;
    }
};

class KDTreeImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_KDTREE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::KDTREE; }

    void doTrain(InputArray points) CV_OVERRIDE
    {
        tr.build(points);
    }

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            res = _results.getMat();
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            nr = _neighborResponses.getMat();
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            d = _dists.getMat();
        }

        for (int i=0; i<test_samples.rows; ++i)
        {
            Mat _res, _nr, _d;
            if (res.rows>i)
            {
                _res = res.row(i);
            }
            if (nr.rows>i)
            {
                _nr = nr.row(i);
            }
            if (d.rows>i)
            {
                _d = d.row(i);
            }
            tr.findNearest(test_samples.row(i), k, Emax, _res, _nr, _d, noArray());
        }

        return result; // currently always 0
    }

    KDTree tr;
};

//================================================================

class KNearestImpl CV_FINAL : public KNearest
{
    inline int getDefaultK() const CV_OVERRIDE { return impl->defaultK; }
    inline void setDefaultK(int val) CV_OVERRIDE { impl->defaultK = val; }
    inline bool getIsClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    inline void setIsClassifier(bool val) CV_OVERRIDE { impl->isclassifier = val; }
    inline int getEmax() const CV_OVERRIDE { return impl->Emax; }
    inline void setEmax(int val) CV_OVERRIDE { impl->Emax = val; }

public:
    int getAlgorithmType() const CV_OVERRIDE
    {
        return impl->getType();
    }
    void setAlgorithmType(int val) CV_OVERRIDE
    {
        if (val != BRUTE_FORCE && val != KDTREE)
            val = BRUTE_FORCE;
        initImpl(val);
    }

public:
    KNearestImpl()
    {
        initImpl(BRUTE_FORCE);
    }
    ~KNearestImpl()
    {
    }

    bool isClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    bool isTrained() const CV_OVERRIDE { return !impl->samples.empty(); }

    int getVarCount() const CV_OVERRIDE { return impl->samples.cols; }

    void write( FileStorage& fs ) const CV_OVERRIDE
    {
        writeFormat(fs);
        impl->write(fs);
    }

    void read( const FileNode& fn ) CV_OVERRIDE
    {
        int algorithmType = BRUTE_FORCE;
        if (fn.name() == NAME_KDTREE)
            algorithmType = KDTREE;
        initImpl(algorithmType);
        impl->read(fn);
    }

    float findNearest( InputArray samples, int k,
                       OutputArray results,
                       OutputArray neighborResponses=noArray(),
                       OutputArray dist=noArray() ) const CV_OVERRIDE
    {
        return impl->findNearest(samples, k, results, neighborResponses, dist);
    }

    float predict(InputArray inputs, OutputArray outputs, int) const CV_OVERRIDE
    {
        return impl->findNearest( inputs, impl->defaultK, outputs, noArray(), noArray() );
    }

    bool train( const Ptr<TrainData>& data, int flags ) CV_OVERRIDE
    {
        return impl->train(data, flags);
    }

    String getDefaultName() const CV_OVERRIDE { return impl->getModelName(); }

protected:
    void initImpl(int algorithmType)
    {
        if (algorithmType != KDTREE)
            impl = makePtr<BruteForceImpl>();
        else
            impl = makePtr<KDTreeImpl>();
    }
    Ptr<Impl> impl;
};

Ptr<KNearest> KNearest::create()
{
    return makePtr<KNearestImpl>();
}

}
}

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

#include "precomp.hpp"
#include "kdtree.hpp"

/****************************************************************************************\
*                              K-Nearest Neighbors Classifier                            *
\****************************************************************************************/

namespace cv {
namespace ml {

const String NAME_BRUTE_FORCE = "opencv_ml_knn";
const String NAME_KDTREE = "opencv_ml_knn_kd";

class Impl
{
public:
    Impl()
    {
        defaultK = 10;
        isclassifier = true;
        Emax = INT_MAX;
    }

    virtual ~Impl() {}
    virtual String getModelName() const = 0;
    virtual int getType() const = 0;
    virtual float findNearest( InputArray _samples, int k,
                               OutputArray _results,
                               OutputArray _neighborResponses,
                               OutputArray _dists ) const = 0;

    bool train( const Ptr<TrainData>& data, int flags )
    {
        Mat new_samples = data->getTrainSamples(ROW_SAMPLE);
        Mat new_responses;
        data->getTrainResponses().convertTo(new_responses, CV_32F);
        bool update = (flags & ml::KNearest::UPDATE_MODEL) != 0 && !samples.empty();

        CV_Assert( new_samples.type() == CV_32F );

        if( !update )
        {
            clear();
        }
        else
        {
            CV_Assert( new_samples.cols == samples.cols &&
                       new_responses.cols == responses.cols );
        }

        samples.push_back(new_samples);
        responses.push_back(new_responses);

        doTrain(samples);

        return true;
    }

    virtual void doTrain(InputArray points) { (void)points; }

    void clear()
    {
        samples.release();
        responses.release();
    }

    void read( const FileNode& fn )
    {
        clear();
        isclassifier = (int)fn["is_classifier"] != 0;
        defaultK = (int)fn["default_k"];

        fn["samples"] >> samples;
        fn["responses"] >> responses;
    }

    void write( FileStorage& fs ) const
    {
        fs << "is_classifier" << (int)isclassifier;
        fs << "default_k" << defaultK;

        fs << "samples" << samples;
        fs << "responses" << responses;
    }

public:
    int defaultK;
    bool isclassifier;
    int Emax;

    Mat samples;
    Mat responses;
};

class BruteForceImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_BRUTE_FORCE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::BRUTE_FORCE; }

    void findNearestCore( const Mat& _samples, int k0, const Range& range,
                          Mat* results, Mat* neighbor_responses,
                          Mat* dists, float* presult ) const
    {
        int testidx, baseidx, i, j, d = samples.cols, nsamples = samples.rows;
        int testcount = range.end - range.start;
        int k = std::min(k0, nsamples);

        AutoBuffer<float> buf(testcount*k*2);
        float* dbuf = buf;
        float* rbuf = dbuf + testcount*k;

        const float* rptr = responses.ptr<float>();

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            for( i = 0; i < k; i++ )
            {
                dbuf[testidx*k + i] = FLT_MAX;
                rbuf[testidx*k + i] = 0.f;
            }
        }

        for( baseidx = 0; baseidx < nsamples; baseidx++ )
        {
            for( testidx = 0; testidx < testcount; testidx++ )
            {
                const float* v = samples.ptr<float>(baseidx);
                const float* u = _samples.ptr<float>(testidx + range.start);

                float s = 0;
                for( i = 0; i <= d - 4; i += 4 )
                {
                    float t0 = u[i] - v[i], t1 = u[i+1] - v[i+1];
                    float t2 = u[i+2] - v[i+2], t3 = u[i+3] - v[i+3];
                    s += t0*t0 + t1*t1 + t2*t2 + t3*t3;
                }

                for( ; i < d; i++ )
                {
                    float t0 = u[i] - v[i];
                    s += t0*t0;
                }

                Cv32suf si;
                si.f = (float)s;
                Cv32suf* dd = (Cv32suf*)(&dbuf[testidx*k]);
                float* nr = &rbuf[testidx*k];

                for( i = k; i > 0; i-- )
                    if( si.i >= dd[i-1].i )
                        break;
                if( i >= k )
                    continue;

                for( j = k-2; j >= i; j-- )
                {
                    dd[j+1].i = dd[j].i;
                    nr[j+1] = nr[j];
                }
                dd[i].i = si.i;
                nr[i] = rptr[baseidx];
            }
        }

        float result = 0.f;
        float inv_scale = 1.f/k;

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            if( neighbor_responses )
            {
                float* nr = neighbor_responses->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    nr[j] = rbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    nr[j] = 0.f;
            }

            if( dists )
            {
                float* dptr = dists->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    dptr[j] = dbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    dptr[j] = 0.f;
            }

            if( results || testidx+range.start == 0 )
            {
                if( !isclassifier || k == 1 )
                {
                    float s = 0.f;
                    for( j = 0; j < k; j++ )
                        s += rbuf[testidx*k + j];
                    result = (float)(s*inv_scale);
                }
                else
                {
                    float* rp = rbuf + testidx*k;
                    std::sort(rp, rp+k);

                    result = rp[0];
                    int prev_start = 0;
                    int best_count = 0;
                    for( j = 1; j <= k; j++ )
                    {
                        if( j == k || rp[j] != rp[j-1] )
                        {
                            int count = j - prev_start;
                            if( best_count < count )
                            {
                                best_count = count;
                                result = rp[j-1];
                            }
                            prev_start = j;
                        }
                    }
                }
                if( results )
                    results->at<float>(testidx + range.start) = result;
                if( presult && testidx+range.start == 0 )
                    *presult = result;
            }
        }
    }

    struct findKNearestInvoker : public ParallelLoopBody
    {
        findKNearestInvoker(const BruteForceImpl* _p, int _k, const Mat& __samples,
                            Mat* __results, Mat* __neighbor_responses, Mat* __dists, float* _presult)
        {
            p = _p;
            k = _k;
            _samples = &__samples;
            _results = __results;
            _neighbor_responses = __neighbor_responses;
            _dists = __dists;
            presult = _presult;
        }

        void operator()(const Range& range) const CV_OVERRIDE
        {
            int delta = std::min(range.end - range.start, 256);
            for( int start = range.start; start < range.end; start += delta )
            {
                p->findNearestCore( *_samples, k, Range(start, std::min(start + delta, range.end)),
                                    _results, _neighbor_responses, _dists, presult );
            }
        }

        const BruteForceImpl* p;
        int k;
        const Mat* _samples;
        Mat* _results;
        Mat* _neighbor_responses;
        Mat* _dists;
        float* presult;
    };

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d, *pres = 0, *pnr = 0, *pd = 0;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            pres = &(res = _results.getMat());
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            pnr = &(nr = _neighborResponses.getMat());
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            pd = &(d = _dists.getMat());
        }

        findKNearestInvoker invoker(this, k, test_samples, pres, pnr, pd, &result);
        parallel_for_(Range(0, testcount), invoker);
        //invoker(Range(0, testcount));
        return result;
    }
};

class KDTreeImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_KDTREE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::KDTREE; }

    void doTrain(InputArray points) CV_OVERRIDE
    {
        tr.build(points);
    }

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            res = _results.getMat();
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            nr = _neighborResponses.getMat();
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            d = _dists.getMat();
        }

        for (int i=0; i<test_samples.rows; ++i)
        {
            Mat _res, _nr, _d;
            if (res.rows>i)
            {
                _res = res.row(i);
            }
            if (nr.rows>i)
            {
                _nr = nr.row(i);
            }
            if (d.rows>i)
            {
                _d = d.row(i);
            }
            tr.findNearest(test_samples.row(i), k, Emax, _res, _nr, _d, noArray());
        }

        return result; // currently always 0
    }

    KDTree tr;
};

//================================================================

class KNearestImpl CV_FINAL : public KNearest
{
    inline int getDefaultK() const CV_OVERRIDE { return impl->defaultK; }
    inline void setDefaultK(int val) CV_OVERRIDE { impl->defaultK = val; }
    inline bool getIsClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    inline void setIsClassifier(bool val) CV_OVERRIDE { impl->isclassifier = val; }
    inline int getEmax() const CV_OVERRIDE { return impl->Emax; }
    inline void setEmax(int val) CV_OVERRIDE { impl->Emax = val; }

public:
    int getAlgorithmType() const CV_OVERRIDE
    {
        return impl->getType();
    }
    void setAlgorithmType(int val) CV_OVERRIDE
    {
        if (val != BRUTE_FORCE && val != KDTREE)
            val = BRUTE_FORCE;

        int k = getDefaultK();
        int e = getEmax();
        bool c = getIsClassifier();

        initImpl(val);

        setDefaultK(k);
        setEmax(e);
        setIsClassifier(c);
    }

public:
    KNearestImpl()
    {
        initImpl(BRUTE_FORCE);
    }
    ~KNearestImpl()
    {
    }

    bool isClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    bool isTrained() const CV_OVERRIDE { return !impl->samples.empty(); }

    int getVarCount() const CV_OVERRIDE { return impl->samples.cols; }

    void write( FileStorage& fs ) const CV_OVERRIDE
    {
        writeFormat(fs);
        impl->write(fs);
    }

    void read( const FileNode& fn ) CV_OVERRIDE
    {
        int algorithmType = BRUTE_FORCE;
        if (fn.name() == NAME_KDTREE)
            algorithmType = KDTREE;
        initImpl(algorithmType);
        impl->read(fn);
    }

    float findNearest( InputArray samples, int k,
                       OutputArray results,
                       OutputArray neighborResponses=noArray(),
                       OutputArray dist=noArray() ) const CV_OVERRIDE
    {
        return impl->findNearest(samples, k, results, neighborResponses, dist);
    }

    float predict(InputArray inputs, OutputArray outputs, int) const CV_OVERRIDE
    {
        return impl->findNearest( inputs, impl->defaultK, outputs, noArray(), noArray() );
    }

    bool train( const Ptr<TrainData>& data, int flags ) CV_OVERRIDE
    {
        return impl->train(data, flags);
    }

    String getDefaultName() const CV_OVERRIDE { return impl->getModelName(); }

protected:
    void initImpl(int algorithmType)
    {
        if (algorithmType != KDTREE)
            impl = makePtr<BruteForceImpl>();
        else
            impl = makePtr<KDTreeImpl>();
    }
    Ptr<Impl> impl;
};

Ptr<KNearest> KNearest::create()
{
    return makePtr<KNearestImpl>();
}

}
}

/* End of file */
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include "canvasgl.h"
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/processors/processor.h>
#include <modules/opengl/inviwoopengl.h>
#include <modules/opengl/glwrap/shader.h>
#include <modules/opengl/image/imagegl.h>
#include <modules/opengl/geometry/meshgl.h>
#include <modules/opengl/glwrap/bufferobjectarray.h>
#include <modules/opengl/buffer/buffergl.h>
#include <modules/opengl/glwrap/textureunit.h>
#include <modules/opengl/rendering/meshdrawergl.h>
#include <modules/opengl/openglcapabilities.h>

namespace inviwo {

const MeshGL* CanvasGL::screenAlignedRectGL_ = nullptr;

CanvasGL::CanvasGL(uvec2 dimensions)
    : Canvas(dimensions)
    , imageGL_(nullptr)
    , image_(nullptr)
    , rectArray_(nullptr)
    , layerType_(COLOR_LAYER)
    , shader_(nullptr)
    , noiseShader_(nullptr)
    , singleChannel_(false) {}

CanvasGL::~CanvasGL() {
    deinitialize();
}

void CanvasGL::initialize() {
    NO_SUPPORTED_GL_THEN_RETURN

    defaultGLState();
    shader_ = new Shader("img_texturequad.vert", "img_texturequad.frag");
    LGL_ERROR;
    noiseShader_ = new Shader("img_texturequad.vert", "img_noise.frag");
    LGL_ERROR;
    Canvas::initialize();
}

void CanvasGL::initializeSquare() {
    NO_SUPPORTED_GL_THEN_RETURN

    const Mesh* screenAlignedRectMesh = dynamic_cast<const Mesh*>(screenAlignedRect_);

    if (screenAlignedRectMesh) {
        screenAlignedRectGL_ = screenAlignedRectMesh->getRepresentation<MeshGL>();
        LGL_ERROR;
    }
}

void CanvasGL::deinitialize() {
    delete shader_;
    shader_ = nullptr;
    delete noiseShader_;
    noiseShader_ = nullptr;
    delete rectArray_;
    rectArray_ = nullptr;
    image_ = nullptr;
    imageGL_ = nullptr;
    Canvas::deinitialize();
}

void CanvasGL::defaultGLState(){
    NO_SUPPORTED_GL_THEN_RETURN
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    LGL_ERROR;
}

void CanvasGL::activate() {}

void CanvasGL::render(const Image* image, LayerType layerType) {
    image_ = image;
    layerType_ = layerType;
    pickingContainer_->setPickingSource(image_);
    if (image_) {
        imageGL_ = image_->getRepresentation<ImageGL>();
        if (imageGL_ && imageGL_->getLayerGL(layerType_)) {
            checkChannels(imageGL_->getLayerGL(layerType_)->getDataFormat()->getComponents());
        } else {
            checkChannels(image_->getDataFormat()->getComponents());
        }
        renderLayer();
    } else {
        imageGL_ = nullptr;
        renderNoise();
    }
}

void CanvasGL::resize(uvec2 size) {
    imageGL_ = nullptr;
    pickingContainer_->setPickingSource(nullptr);
    Canvas::resize(size);
}

void CanvasGL::glSwapBuffers() {}

void CanvasGL::update() {
    renderLayer();
}

void CanvasGL::attachImagePlanRect(BufferObjectArray* arrayObject) {
    if (arrayObject) {
        arrayObject->bind();
        arrayObject->attachBufferObject(
            screenAlignedRectGL_->getBufferGL(0)->getBufferObject(),
            POSITION_ATTRIB);
        arrayObject->attachBufferObject(
            screenAlignedRectGL_->getBufferGL(1)->getBufferObject(),
            TEXCOORD_ATTRIB);
        arrayObject->unbind();
    }
}

void CanvasGL::singleDrawImagePlaneRect() {
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void CanvasGL::multiDrawImagePlaneRect(int instances) {
    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instances);
}

void CanvasGL::renderLayer() {
    if (imageGL_) {
        const LayerGL* layerGL = imageGL_->getLayerGL(layerType_);
        if (layerGL) {
            TextureUnit textureUnit;
            layerGL->bindTexture(textureUnit.getEnum());
            renderTexture(textureUnit.getUnitNumber());
            layerGL->unbindTexture();
            return;
        } else {
            renderNoise();
        }
    }
    if (!image_) renderNoise();
}

void CanvasGL::renderNoise() {
    if (!noiseShader_)
        return;
    activate();
    glViewport(0, 0, getScreenDimensions().x, getScreenDimensions().y);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    noiseShader_->activate();
    drawRect();
    noiseShader_->deactivate();
    glSwapBuffers();
    activateDefaultRenderContext();
}

void CanvasGL::renderTexture(int unitNumber) {
    if (!shader_)
        return;
    activate();
    glViewport(0, 0, getScreenDimensions().x, getScreenDimensions().y);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    shader_->activate();
    shader_->setUniform("tex_", unitNumber);
    drawRect();
    shader_->deactivate();
    glDisable(GL_BLEND);
    glSwapBuffers();
    activateDefaultRenderContext();
}

void CanvasGL::drawRect() {
    delete rectArray_;
    rectArray_ = new BufferObjectArray();
    rectArray_->bind();
    rectArray_->attachBufferObject(
        screenAlignedRectGL_->getBufferGL(0)->getBufferObject(),
        POSITION_ATTRIB);
    rectArray_->attachBufferObject(
        screenAlignedRectGL_->getBufferGL(1)->getBufferObject(),
        TEXCOORD_ATTRIB);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    rectArray_->unbind();
}

void CanvasGL::checkChannels(int channels) {
    if (!singleChannel_ && channels == 1) {
        shader_->getFragmentShaderObject()->addShaderDefine("SINGLE_CHANNEL");
        shader_->getFragmentShaderObject()->build();
        shader_->link();
        singleChannel_ = true;
    } else if (singleChannel_ && channels == 4) {
        shader_->getFragmentShaderObject()->removeShaderDefine("SINGLE_CHANNEL");
        shader_->getFragmentShaderObject()->build();
        shader_->link();
        singleChannel_ = false;
    }
}

const LayerRAM* CanvasGL::getDepthLayerRAM() const{
    const Layer* depthLayer = image_->getDepthLayer();
    if (depthLayer) {
        return depthLayer->getRepresentation<LayerRAM>();
    }
    else
        return nullptr;
}

double CanvasGL::getDepthValueAtCoord(uvec2 coord) const{
    const LayerRAM* depthLayerRAM = getDepthLayerRAM();
    if (depthLayerRAM) {
        // Convert to normalized device coordinates
        return 2.0*depthLayerRAM->getValueAsSingleDouble(coord)-1.0;
    }
    else
        return 1.0;
}

void CanvasGL::enableDrawImagePlaneRect() {
        screenAlignedRectGL_->enable();
}

void CanvasGL::disableDrawImagePlaneRect() {
    screenAlignedRectGL_->disable();
}

void  CanvasGL::setProcessorWidgetOwner(ProcessorWidget* widget) {
    //Clear internal state
    image_ = nullptr;
    imageGL_ = nullptr;
    pickingContainer_->setPickingSource(nullptr);
    Canvas::setProcessorWidgetOwner(widget);
}

}  // namespace
<commit_msg>OpenGL: Nullptr check when sampling canvas image.<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include "canvasgl.h"
#include <inviwo/core/datastructures/geometry/mesh.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/processors/processor.h>
#include <modules/opengl/inviwoopengl.h>
#include <modules/opengl/glwrap/shader.h>
#include <modules/opengl/image/imagegl.h>
#include <modules/opengl/geometry/meshgl.h>
#include <modules/opengl/glwrap/bufferobjectarray.h>
#include <modules/opengl/buffer/buffergl.h>
#include <modules/opengl/glwrap/textureunit.h>
#include <modules/opengl/rendering/meshdrawergl.h>
#include <modules/opengl/openglcapabilities.h>

namespace inviwo {

const MeshGL* CanvasGL::screenAlignedRectGL_ = nullptr;

CanvasGL::CanvasGL(uvec2 dimensions)
    : Canvas(dimensions)
    , imageGL_(nullptr)
    , image_(nullptr)
    , rectArray_(nullptr)
    , layerType_(COLOR_LAYER)
    , shader_(nullptr)
    , noiseShader_(nullptr)
    , singleChannel_(false) {}

CanvasGL::~CanvasGL() {
    deinitialize();
}

void CanvasGL::initialize() {
    NO_SUPPORTED_GL_THEN_RETURN

    defaultGLState();
    shader_ = new Shader("img_texturequad.vert", "img_texturequad.frag");
    LGL_ERROR;
    noiseShader_ = new Shader("img_texturequad.vert", "img_noise.frag");
    LGL_ERROR;
    Canvas::initialize();
}

void CanvasGL::initializeSquare() {
    NO_SUPPORTED_GL_THEN_RETURN

    const Mesh* screenAlignedRectMesh = dynamic_cast<const Mesh*>(screenAlignedRect_);

    if (screenAlignedRectMesh) {
        screenAlignedRectGL_ = screenAlignedRectMesh->getRepresentation<MeshGL>();
        LGL_ERROR;
    }
}

void CanvasGL::deinitialize() {
    delete shader_;
    shader_ = nullptr;
    delete noiseShader_;
    noiseShader_ = nullptr;
    delete rectArray_;
    rectArray_ = nullptr;
    image_ = nullptr;
    imageGL_ = nullptr;
    Canvas::deinitialize();
}

void CanvasGL::defaultGLState(){
    NO_SUPPORTED_GL_THEN_RETURN
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    LGL_ERROR;
}

void CanvasGL::activate() {}

void CanvasGL::render(const Image* image, LayerType layerType) {
    image_ = image;
    layerType_ = layerType;
    pickingContainer_->setPickingSource(image_);
    if (image_) {
        imageGL_ = image_->getRepresentation<ImageGL>();
        if (imageGL_ && imageGL_->getLayerGL(layerType_)) {
            checkChannels(imageGL_->getLayerGL(layerType_)->getDataFormat()->getComponents());
        } else {
            checkChannels(image_->getDataFormat()->getComponents());
        }
        renderLayer();
    } else {
        imageGL_ = nullptr;
        renderNoise();
    }
}

void CanvasGL::resize(uvec2 size) {
    imageGL_ = nullptr;
    pickingContainer_->setPickingSource(nullptr);
    Canvas::resize(size);
}

void CanvasGL::glSwapBuffers() {}

void CanvasGL::update() {
    renderLayer();
}

void CanvasGL::attachImagePlanRect(BufferObjectArray* arrayObject) {
    if (arrayObject) {
        arrayObject->bind();
        arrayObject->attachBufferObject(
            screenAlignedRectGL_->getBufferGL(0)->getBufferObject(),
            POSITION_ATTRIB);
        arrayObject->attachBufferObject(
            screenAlignedRectGL_->getBufferGL(1)->getBufferObject(),
            TEXCOORD_ATTRIB);
        arrayObject->unbind();
    }
}

void CanvasGL::singleDrawImagePlaneRect() {
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void CanvasGL::multiDrawImagePlaneRect(int instances) {
    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, instances);
}

void CanvasGL::renderLayer() {
    if (imageGL_) {
        const LayerGL* layerGL = imageGL_->getLayerGL(layerType_);
        if (layerGL) {
            TextureUnit textureUnit;
            layerGL->bindTexture(textureUnit.getEnum());
            renderTexture(textureUnit.getUnitNumber());
            layerGL->unbindTexture();
            return;
        } else {
            renderNoise();
        }
    }
    if (!image_) renderNoise();
}

void CanvasGL::renderNoise() {
    if (!noiseShader_)
        return;
    activate();
    glViewport(0, 0, getScreenDimensions().x, getScreenDimensions().y);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    noiseShader_->activate();
    drawRect();
    noiseShader_->deactivate();
    glSwapBuffers();
    activateDefaultRenderContext();
}

void CanvasGL::renderTexture(int unitNumber) {
    if (!shader_)
        return;
    activate();
    glViewport(0, 0, getScreenDimensions().x, getScreenDimensions().y);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    shader_->activate();
    shader_->setUniform("tex_", unitNumber);
    drawRect();
    shader_->deactivate();
    glDisable(GL_BLEND);
    glSwapBuffers();
    activateDefaultRenderContext();
}

void CanvasGL::drawRect() {
    delete rectArray_;
    rectArray_ = new BufferObjectArray();
    rectArray_->bind();
    rectArray_->attachBufferObject(
        screenAlignedRectGL_->getBufferGL(0)->getBufferObject(),
        POSITION_ATTRIB);
    rectArray_->attachBufferObject(
        screenAlignedRectGL_->getBufferGL(1)->getBufferObject(),
        TEXCOORD_ATTRIB);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    rectArray_->unbind();
}

void CanvasGL::checkChannels(int channels) {
    if (!singleChannel_ && channels == 1) {
        shader_->getFragmentShaderObject()->addShaderDefine("SINGLE_CHANNEL");
        shader_->getFragmentShaderObject()->build();
        shader_->link();
        singleChannel_ = true;
    } else if (singleChannel_ && channels == 4) {
        shader_->getFragmentShaderObject()->removeShaderDefine("SINGLE_CHANNEL");
        shader_->getFragmentShaderObject()->build();
        shader_->link();
        singleChannel_ = false;
    }
}

const LayerRAM* CanvasGL::getDepthLayerRAM() const{
    if (image_) {
        const Layer* depthLayer = image_->getDepthLayer();
        if (depthLayer) {
            return depthLayer->getRepresentation<LayerRAM>();
        }
        else
            return nullptr;
    }
    else
        return nullptr;
}

double CanvasGL::getDepthValueAtCoord(uvec2 coord) const{
    const LayerRAM* depthLayerRAM = getDepthLayerRAM();
    if (depthLayerRAM) {
        // Convert to normalized device coordinates
        return 2.0*depthLayerRAM->getValueAsSingleDouble(coord)-1.0;
    }
    else
        return 1.0;
}

void CanvasGL::enableDrawImagePlaneRect() {
        screenAlignedRectGL_->enable();
}

void CanvasGL::disableDrawImagePlaneRect() {
    screenAlignedRectGL_->disable();
}

void  CanvasGL::setProcessorWidgetOwner(ProcessorWidget* widget) {
    //Clear internal state
    image_ = nullptr;
    imageGL_ = nullptr;
    pickingContainer_->setPickingSource(nullptr);
    Canvas::setProcessorWidgetOwner(widget);
}

}  // namespace
<|endoftext|>


<commit_before>/*
 * C api for arduino esp8266 web server
 * To be built under ARDUINO IDE only (as a part of libdfu for arduino)
 */
#include <ESP8266WebServer.h>
#include "arduino-server.h"

static ESP8266WebServer *server;
static int first_chunk, error, chunk_ready, last_chunk;
static uint8_t *current_chunk;
static int current_chunk_len;
static int finalized;

static void handle_ota_post(void)
{
	HTTPUpload& upload = server->upload();
	int n, tot;

	tot = server->arg("totchunk").toInt();
	n = server->arg("numchunk").toInt();
	first_chunk = n == 1;
	last_chunk = n == tot;
	chunk_ready = 1;
	current_chunk = upload.buf;
	current_chunk_len = upload.currentSize;
}

extern "C" int arduino_server_send(int code, const char *msg)
{
	server->send(code, "text/plain", msg);
	return 0;
}

extern "C" int arduino_server_poll(void)
{
	server->handleClient();
	return chunk_ready;
}

extern "C" void arduino_server_ack(void)
{
	chunk_ready = 0;
}

extern "C" void arduino_server_get_data(struct arduino_server_data *sd)
{
	sd->chunk_ready = chunk_ready;
	sd->first_chunk = first_chunk;
	sd->last_chunk = last_chunk;
	sd->error = error;
	sd->chunk_ptr = current_chunk;
	sd->chunk_len = current_chunk_len;
}

extern "C" int arduino_server_init(void *_srv)
{
	server = (ESP8266WebServer *)_srv;
	if (!finalized) {
		server->on("/otafile", HTTP_POST, handle_ota_post);
		server->begin();
	}
	finalized = 0;
}

extern "C" void arduino_server_fini(void)
{
	/*
	 * ESP8266WebServer has no end() method.
	 * We just take note that the server has been finalized and avoid
	 * trying to re-initialize it next time
	 */
	finalized = 1;
}
<commit_msg>arduino-server.cpp, arduino_server_init(): function returns an integer<commit_after>/*
 * C api for arduino esp8266 web server
 * To be built under ARDUINO IDE only (as a part of libdfu for arduino)
 */
#include <ESP8266WebServer.h>
#include "arduino-server.h"

static ESP8266WebServer *server;
static int first_chunk, error, chunk_ready, last_chunk;
static uint8_t *current_chunk;
static int current_chunk_len;
static int finalized;

static void handle_ota_post(void)
{
	HTTPUpload& upload = server->upload();
	int n, tot;

	tot = server->arg("totchunk").toInt();
	n = server->arg("numchunk").toInt();
	first_chunk = n == 1;
	last_chunk = n == tot;
	chunk_ready = 1;
	current_chunk = upload.buf;
	current_chunk_len = upload.currentSize;
}

extern "C" int arduino_server_send(int code, const char *msg)
{
	server->send(code, "text/plain", msg);
	return 0;
}

extern "C" int arduino_server_poll(void)
{
	server->handleClient();
	return chunk_ready;
}

extern "C" void arduino_server_ack(void)
{
	chunk_ready = 0;
}

extern "C" void arduino_server_get_data(struct arduino_server_data *sd)
{
	sd->chunk_ready = chunk_ready;
	sd->first_chunk = first_chunk;
	sd->last_chunk = last_chunk;
	sd->error = error;
	sd->chunk_ptr = current_chunk;
	sd->chunk_len = current_chunk_len;
}

extern "C" int arduino_server_init(void *_srv)
{
	server = (ESP8266WebServer *)_srv;
	if (!finalized) {
		server->on("/otafile", HTTP_POST, handle_ota_post);
		server->begin();
	}
	finalized = 0;
	return 0;
}

extern "C" void arduino_server_fini(void)
{
	/*
	 * ESP8266WebServer has no end() method.
	 * We just take note that the server has been finalized and avoid
	 * trying to re-initialize it next time
	 */
	finalized = 1;
}
<|endoftext|>


<commit_before>#include "variant/pwm_platform.hpp"

#include "hal.h"

// TODO(yoos): v4.0 will switch these around so we can share a 50 Hz timer
// channel between servos and status LEDs.
static const PWMConfig PWMD1_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_DISABLED, NULL}
  },   // Channel configurations
  0,0   // HW dependent
};

static const PWMConfig PWMD3_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_DISABLED, NULL},      // RSSI
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},   // Status R
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},   // Status G
    {PWM_OUTPUT_ACTIVE_HIGH, NULL}    // Status B
  },   // Channel configurations
  0,0   // HW dependent
};

static const PWMConfig PWMD4_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL}
  },   // Channel configurations
  0,0   // HW dependent
};

PWMPlatform::PWMPlatform() {
  // TIM1
  pwmStart(&PWMD1, &PWMD1_CONFIG);
  palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(1));
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1));

  // TIM3
  pwmStart(&PWMD3, &PWMD3_CONFIG);
  palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATE(2));

  // TIM4
  pwmStart(&PWMD4, &PWMD4_CONFIG);
  palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(2));
}

void PWMPlatform::set(std::uint8_t ch, float dc) {
  if (ch < 4) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD1, dc * 10000.0f);
    pwmEnableChannel(&PWMD1, ch, width);
  }
  else if (ch < 8) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD4, dc * 10000.0f);
    pwmEnableChannel(&PWMD4, ch-4, width);
  }
  else if (ch < 12) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD3, dc * 10000.0f);
    pwmEnableChannel(&PWMD3, ch-8, width);
  }
}

float PWMPlatform::get(std::uint8_t ch) {
  if (ch == 0) {
    if (palReadPad(GPIOB, 7)) {
      return 1.0;
    }
  }
  return 0.0;
}
<commit_msg>Remove obsolete PWM getter.<commit_after>#include "variant/pwm_platform.hpp"

#include "hal.h"

// TODO(yoos): v4.0 will switch these around so we can share a 50 Hz timer
// channel between servos and status LEDs.
static const PWMConfig PWMD1_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_DISABLED, NULL}
  },   // Channel configurations
  0,0   // HW dependent
};

static const PWMConfig PWMD3_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_DISABLED, NULL},      // RSSI
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},   // Status R
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},   // Status G
    {PWM_OUTPUT_ACTIVE_HIGH, NULL}    // Status B
  },   // Channel configurations
  0,0   // HW dependent
};

static const PWMConfig PWMD4_CONFIG {
  500000,    // 500 kHz PWM clock frequency.
  1000,      // PWM period 2.0 ms.
  NULL,      // No callback.
  {
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_DISABLED, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL},
    {PWM_OUTPUT_ACTIVE_HIGH, NULL}
  },   // Channel configurations
  0,0   // HW dependent
};

PWMPlatform::PWMPlatform() {
  // TIM1
  pwmStart(&PWMD1, &PWMD1_CONFIG);
  palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(1));
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1));

  // TIM3
  pwmStart(&PWMD3, &PWMD3_CONFIG);
  palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATE(2));

  // TIM4
  pwmStart(&PWMD4, &PWMD4_CONFIG);
  palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(2));
  palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(2));
}

void PWMPlatform::set(std::uint8_t ch, float dc) {
  if (ch < 4) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD1, dc * 10000.0f);
    pwmEnableChannel(&PWMD1, ch, width);
  }
  else if (ch < 8) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD4, dc * 10000.0f);
    pwmEnableChannel(&PWMD4, ch-4, width);
  }
  else if (ch < 12) {
    pwmcnt_t width = PWM_PERCENTAGE_TO_WIDTH(&PWMD3, dc * 10000.0f);
    pwmEnableChannel(&PWMD3, ch-8, width);
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
              Anders Knospe - last modified on 26 March 2016

//Lauches phi analysis with rsn mini package
//Allows basic configuration of pile-up check and event cuts
****************************************************************************/

enum pairYCutSet { kPairDefault=0,
		   kCentral //=1
                 };

enum eventCutSet { kEvtDefault=0,
		   kNoPileUpCut, //=1
		   kDefaultVtx12,//=2
		   kDefaultVtx8, //=3
		   kDefaultVtx5, //=4
		   kMCEvtDefault, //=5
		   kSpecial1, //=6
		   kSpecial2, //=7
		   kNoEvtSel //=8
                 };

enum eventMixConfig { kDisabled = -1,
		      kMixDefault,//=0 //10 events, Dvz = 1cm, DC = 10
		      k5Evts, //=1 //5 events, Dvz = 1cm, DC = 10
		      k5Cent,  //=2 //10 events, Dvz = 1cm, DC = 5
		      k5Evts5Cent
                    };

AliRsnMiniAnalysisTask * AddTaskPhiPP5TeV_PID
(
 Bool_t      isMC=kFALSE,
 Bool_t      isPP=kTRUE,
 TString     outNameSuffix="tpc2stof3sveto",
 Int_t       evtCutSetID=0,
 Int_t       pairCutSetID=0,
 Int_t       mixingConfigID=0,
 Int_t       aodFilterBit=5,
 Int_t       customQualityCutsID=1,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutKaCandidate=AliRsnCutSetDaughterParticle::kTPCpidTOFveto3s,
 Float_t     nsigmaKa=2.,
 Bool_t      enableMonitor=kTRUE,
 Bool_t      IsMcTrueOnly=kFALSE,
 TString     monitorOpt="NoSIGN",
 Bool_t      useMixLS=0,
 Bool_t      checkReflex=0,
 AliRsnMiniValue::EType yaxisvar=AliRsnMiniValue::kPt,
 TString     polarizationOpt="" /* J - Jackson,T - Transversity */
)
{
  //-------------------------------------------
  // event cuts
  //-------------------------------------------
  UInt_t      triggerMask=AliVEvent::kINT7;
  if(isMC && evtCutSetID==eventCutSet::kNoEvtSel) triggerMask=AliVEvent::kAny;
  Bool_t      rejectPileUp=kTRUE;
  Double_t    vtxZcut=10.0;//cm, default cut on vtx z
  Int_t       MultBins=aodFilterBit/100;

  if(evtCutSetID==eventCutSet::kDefaultVtx12) vtxZcut=12.0; //cm
  if(evtCutSetID==eventCutSet::kDefaultVtx8) vtxZcut=8.0; //cm
  if(evtCutSetID==eventCutSet::kDefaultVtx5) vtxZcut=5.0; //cm
  if(evtCutSetID==eventCutSet::kNoPileUpCut) rejectPileUp=kFALSE;
  if(evtCutSetID==eventCutSet::kSpecial2) vtxZcut=1.e6;//off

  if(!isPP || isMC || MultBins) rejectPileUp=kFALSE;

  //-------------------------------------------
  //pair cuts
  //-------------------------------------------
  Double_t    minYlab=-0.5;
  Double_t    maxYlab= 0.5;

  if(pairCutSetID==pairYCutSet::kCentral){//|y_cm|<0.3
    minYlab=-0.3; maxYlab=0.3;
  }

  //-------------------------------------------
  //mixing settings
  //-------------------------------------------
  Int_t       nmix=0;
  Float_t     maxDiffVzMix=1.;
  Float_t     maxDiffMultMix=10.;

  if(mixingConfigID==eventMixConfig::kMixDefault) nmix=10;
  if(mixingConfigID==eventMixConfig::k5Evts) nmix=5;
  if(mixingConfigID==eventMixConfig::k5Cent) maxDiffMultMix=5;
  if(mixingConfigID==eventMixConfig::k5Evts5Cent){nmix=5; maxDiffMultMix=5;}

  // -- INITIALIZATION ----------------------------------------------------------------------------
  // retrieve analysis manager

  AliAnalysisManager* mgr=AliAnalysisManager::GetAnalysisManager();
  if(!mgr){
    ::Error("AddTaskPhiPP5TeV_PID", "No analysis manager to connect to.");
    return NULL;
  }

  // create the task and configure
  TString taskName=Form("phi%s%s_%i%i",(isPP? "pp" : "PbPb"),(isMC ? "MC" : "Data"),(Int_t)cutKaCandidate);
  AliRsnMiniAnalysisTask* task=new AliRsnMiniAnalysisTask(taskName.Data(),isMC);
  //task->UseESDTriggerMask(triggerMask); //ESD ****** check this *****
  task->SelectCollisionCandidates(triggerMask); //AOD

  if(isPP){
    if(MultBins==1) task->UseMultiplicity("AliMultSelection_V0M");
    else if(MultBins==2) task->UseMultiplicity("AliMultSelection_RefMult08");
    else task->UseMultiplicity("QUALITY");
  }else task->UseCentrality("V0M");

  // set event mixing options
  task->UseContinuousMix();
  //task->UseBinnedMix();
  task->SetNMix(nmix);
  task->SetMaxDiffVz(maxDiffVzMix);
  task->SetMaxDiffMult(maxDiffMultMix);
  ::Info("AddTaskPhiPP5TeV_PID", Form("Event mixing configuration: \n events to mix = %i \n max diff. vtxZ = cm %5.3f \n max diff multi = %5.3f", nmix, maxDiffVzMix, maxDiffMultMix));

  mgr->AddTask(task);

  // cut on primary vertex:
  // - 2nd argument --> |Vz| range
  // - 3rd argument --> minimum required number of contributors to vtx
  // - 4th argument --> tells if TPC stand-alone vertexes must be accepted

  AliRsnCutPrimaryVertex* cutVertex=0;
  if(evtCutSetID!=eventCutSet::kSpecial1 && evtCutSetID!=eventCutSet::kNoEvtSel && !MultBins){
    cutVertex=new AliRsnCutPrimaryVertex("cutVertex",vtxZcut,0,kFALSE);
    cutVertex->SetCheckZResolutionSPD();
    cutVertex->SetCheckDispersionSPD();
    cutVertex->SetCheckZDifferenceSPDTrack();
  }

  AliRsnCutEventUtils* cutEventUtils=0;
  if(evtCutSetID!=eventCutSet::kNoEvtSel){
    cutEventUtils=new AliRsnCutEventUtils("cutEventUtils",kTRUE,rejectPileUp);
    if(!MultBins){
      cutEventUtils->SetCheckIncompleteDAQ();
      cutEventUtils->SetCheckSPDClusterVsTrackletBG();
      cutEventUtils->SetCheckInelGt0SPDtracklets();
    }else{
      cutEventUtils->SetRemovePileUppA2013(kFALSE);
      cutEventUtils->SetCheckAcceptedMultSelection();
    }
  }

  if(isPP && (!isMC) && cutVertex){
    cutVertex->SetCheckPileUp(rejectPileUp);// set the check for pileup
    ::Info("AddTaskPhiPP5TeV_PID", Form(":::::::::::::::::: Pile-up rejection mode: %s", (rejectPileUp)?"ON":"OFF"));
  }

  // define and fill cut set for event cut
  AliRsnCutSet* eventCuts=0;
  if(cutEventUtils || cutVertex){
    eventCuts=new AliRsnCutSet("eventCuts",AliRsnTarget::kEvent);

    if(cutEventUtils && cutVertex){
      eventCuts->AddCut(cutEventUtils);
      eventCuts->AddCut(cutVertex);
      eventCuts->SetCutScheme(Form("%s&%s",cutEventUtils->GetName(),cutVertex->GetName()));
    }else if(cutEventUtils && !cutVertex){
      eventCuts->AddCut(cutEventUtils);
      eventCuts->SetCutScheme(Form("%s",cutEventUtils->GetName()));
    }else if(!cutEventUtils && !cutVertex){
      eventCuts->AddCut(cutVertex);
      eventCuts->SetCutScheme(Form("%s",cutVertex->GetName()));
    }

    task->SetEventCuts(eventCuts);
  }

  // -- EVENT-ONLY COMPUTATIONS -------------------------------------------------------------------

  //vertex
  Int_t vtxID=task->CreateValue(AliRsnMiniValue::kVz,kFALSE);
  AliRsnMiniOutput* outVtx=task->CreateOutput("eventVtx","HIST","EVENT");
  outVtx->AddAxis(vtxID,240,-12.0,12.0);

  //multiplicity or centrality
  Int_t multID=task->CreateValue(AliRsnMiniValue::kMult,kFALSE);
  AliRsnMiniOutput* outMult=task->CreateOutput("eventMult","HIST","EVENT");
  if(isPP && !MultBins) outMult->AddAxis(multID,400,0.5,400.5);
  else outMult->AddAxis(multID,110,0.,110.);

  TH2F* hvz=new TH2F("hVzVsCent","",110,0.,110., 240,-12.0,12.0);
  task->SetEventQAHist("vz",hvz);//plugs this histogram into the fHAEventVz data member

  TH2F* hmc=new TH2F("MultiVsCent","", 110,0.,110., 400,0.5,400.5);
  hmc->GetYaxis()->SetTitle("QUALITY");
  task->SetEventQAHist("multicent",hmc);//plugs this histogram into the fHAEventMultiCent data member

  // -- PAIR CUTS (common to all resonances) ------------------------------------------------------

  AliRsnCutMiniPair* cutY=new AliRsnCutMiniPair("cutRapidity",AliRsnCutMiniPair::kRapidityRange);
  cutY->SetRangeD(minYlab,maxYlab);

  AliRsnCutSet* cutsPair=new AliRsnCutSet("pairCuts",AliRsnTarget::kMother);
  cutsPair->AddCut(cutY);
  cutsPair->SetCutScheme(cutY->GetName());

  // -- CONFIG ANALYSIS --------------------------------------------------------------------------

  gROOT->LoadMacro("$ALICE_PHYSICS/PWGLF/RESONANCES/macros/mini/ConfigPhiPP5TeV_PID.C");
  if(!ConfigPhiPP5TeV_PID(task,isMC,isPP,"",cutsPair,aodFilterBit,customQualityCutsID,cutKaCandidate,nsigmaKa,enableMonitor,isMC&IsMcTrueOnly,monitorOpt.Data(),useMixLS,isMC&checkReflex,yaxisvar,polarizationOpt)) return 0x0;

  // -- CONTAINERS --------------------------------------------------------------------------------

  TString outputFileName = AliAnalysisManager::GetCommonFileName();
  //  outputFileName += ":Rsn";
  Printf("AddAnalysisTaskPhiPP5TeV_PID - Set OutputFileName : \n %s\n",outputFileName.Data());

  AliAnalysisDataContainer* output=mgr->CreateContainer(Form("RsnOut_%s",outNameSuffix.Data()),
							TList::Class(),
							AliAnalysisManager::kOutputContainer,
							outputFileName);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output);

  return task;
}

<commit_msg>Correction on a event cut for phi analysis in pp at 5 TeV<commit_after>/***************************************************************************
              Anders Knospe - last modified on 26 March 2016

//Lauches phi analysis with rsn mini package
//Allows basic configuration of pile-up check and event cuts
****************************************************************************/

enum pairYCutSet { kPairDefault=0,
		   kCentral //=1
                 };

enum eventCutSet { kEvtDefault=0,
		   kNoPileUpCut, //=1
		   kDefaultVtx12,//=2
		   kDefaultVtx8, //=3
		   kDefaultVtx5, //=4
		   kMCEvtDefault, //=5
		   kSpecial1, //=6
		   kSpecial2, //=7
		   kNoEvtSel //=8
                 };

enum eventMixConfig { kDisabled = -1,
		      kMixDefault,//=0 //10 events, Dvz = 1cm, DC = 10
		      k5Evts, //=1 //5 events, Dvz = 1cm, DC = 10
		      k5Cent,  //=2 //10 events, Dvz = 1cm, DC = 5
		      k5Evts5Cent
                    };

AliRsnMiniAnalysisTask * AddTaskPhiPP5TeV_PID
(
 Bool_t      isMC=kFALSE,
 Bool_t      isPP=kTRUE,
 TString     outNameSuffix="tpc2stof3sveto",
 Int_t       evtCutSetID=0,
 Int_t       pairCutSetID=0,
 Int_t       mixingConfigID=0,
 Int_t       aodFilterBit=5,
 Int_t       customQualityCutsID=1,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutKaCandidate=AliRsnCutSetDaughterParticle::kTPCpidTOFveto3s,
 Float_t     nsigmaKa=2.,
 Bool_t      enableMonitor=kTRUE,
 Bool_t      IsMcTrueOnly=kFALSE,
 TString     monitorOpt="NoSIGN",
 Bool_t      useMixLS=0,
 Bool_t      checkReflex=0,
 AliRsnMiniValue::EType yaxisvar=AliRsnMiniValue::kPt,
 TString     polarizationOpt="" /* J - Jackson,T - Transversity */
)
{
  //-------------------------------------------
  // event cuts
  //-------------------------------------------
  UInt_t      triggerMask=AliVEvent::kINT7;
  if(isMC && evtCutSetID==eventCutSet::kNoEvtSel) triggerMask=AliVEvent::kAny;
  Bool_t      rejectPileUp=kTRUE;
  Double_t    vtxZcut=10.0;//cm, default cut on vtx z
  Int_t       MultBins=aodFilterBit/100;

  if(evtCutSetID==eventCutSet::kDefaultVtx12) vtxZcut=12.0; //cm
  if(evtCutSetID==eventCutSet::kDefaultVtx8) vtxZcut=8.0; //cm
  if(evtCutSetID==eventCutSet::kDefaultVtx5) vtxZcut=5.0; //cm
  if(evtCutSetID==eventCutSet::kNoPileUpCut) rejectPileUp=kFALSE;
  if(evtCutSetID==eventCutSet::kSpecial2) vtxZcut=1.e6;//off

  if(!isPP || isMC || MultBins) rejectPileUp=kFALSE;

  //-------------------------------------------
  //pair cuts
  //-------------------------------------------
  Double_t    minYlab=-0.5;
  Double_t    maxYlab= 0.5;

  if(pairCutSetID==pairYCutSet::kCentral){//|y_cm|<0.3
    minYlab=-0.3; maxYlab=0.3;
  }

  //-------------------------------------------
  //mixing settings
  //-------------------------------------------
  Int_t       nmix=0;
  Float_t     maxDiffVzMix=1.;
  Float_t     maxDiffMultMix=10.;

  if(mixingConfigID==eventMixConfig::kMixDefault) nmix=10;
  if(mixingConfigID==eventMixConfig::k5Evts) nmix=5;
  if(mixingConfigID==eventMixConfig::k5Cent) maxDiffMultMix=5;
  if(mixingConfigID==eventMixConfig::k5Evts5Cent){nmix=5; maxDiffMultMix=5;}

  // -- INITIALIZATION ----------------------------------------------------------------------------
  // retrieve analysis manager

  AliAnalysisManager* mgr=AliAnalysisManager::GetAnalysisManager();
  if(!mgr){
    ::Error("AddTaskPhiPP5TeV_PID", "No analysis manager to connect to.");
    return NULL;
  }

  // create the task and configure
  TString taskName=Form("phi%s%s_%i%i",(isPP? "pp" : "PbPb"),(isMC ? "MC" : "Data"),(Int_t)cutKaCandidate);
  AliRsnMiniAnalysisTask* task=new AliRsnMiniAnalysisTask(taskName.Data(),isMC);
  //task->UseESDTriggerMask(triggerMask); //ESD ****** check this *****
  task->SelectCollisionCandidates(triggerMask); //AOD

  if(isPP){
    if(MultBins==1) task->UseMultiplicity("AliMultSelection_V0M");
    else if(MultBins==2) task->UseMultiplicity("AliMultSelection_RefMult08");
    else task->UseMultiplicity("QUALITY");
  }else task->UseCentrality("V0M");

  // set event mixing options
  task->UseContinuousMix();
  //task->UseBinnedMix();
  task->SetNMix(nmix);
  task->SetMaxDiffVz(maxDiffVzMix);
  task->SetMaxDiffMult(maxDiffMultMix);
  ::Info("AddTaskPhiPP5TeV_PID", Form("Event mixing configuration: \n events to mix = %i \n max diff. vtxZ = cm %5.3f \n max diff multi = %5.3f", nmix, maxDiffVzMix, maxDiffMultMix));

  mgr->AddTask(task);

  // cut on primary vertex:
  // - 2nd argument --> |Vz| range
  // - 3rd argument --> minimum required number of contributors to vtx
  // - 4th argument --> tells if TPC stand-alone vertexes must be accepted

  AliRsnCutPrimaryVertex* cutVertex=0;
  if(evtCutSetID!=eventCutSet::kSpecial1 && evtCutSetID!=eventCutSet::kNoEvtSel && !MultBins){
    cutVertex=new AliRsnCutPrimaryVertex("cutVertex",vtxZcut,0,kFALSE);
    cutVertex->SetCheckZResolutionSPD();
    cutVertex->SetCheckDispersionSPD();
    cutVertex->SetCheckZDifferenceSPDTrack();
  }

  AliRsnCutEventUtils* cutEventUtils=0;
  if(evtCutSetID!=eventCutSet::kNoEvtSel){
    cutEventUtils=new AliRsnCutEventUtils("cutEventUtils",kTRUE,rejectPileUp);
    if(!MultBins){
      cutEventUtils->SetCheckIncompleteDAQ();
      cutEventUtils->SetCheckSPDClusterVsTrackletBG();
    }else{
      //cutEventUtils->SetCheckInelGt0SPDtracklets();
      cutEventUtils->SetRemovePileUppA2013(kFALSE);
      cutEventUtils->SetCheckAcceptedMultSelection();
    }
  }

  if(isPP && (!isMC) && cutVertex){
    cutVertex->SetCheckPileUp(rejectPileUp);// set the check for pileup
    ::Info("AddTaskPhiPP5TeV_PID", Form(":::::::::::::::::: Pile-up rejection mode: %s", (rejectPileUp)?"ON":"OFF"));
  }

  // define and fill cut set for event cut
  AliRsnCutSet* eventCuts=0;
  if(cutEventUtils || cutVertex){
    eventCuts=new AliRsnCutSet("eventCuts",AliRsnTarget::kEvent);

    if(cutEventUtils && cutVertex){
      eventCuts->AddCut(cutEventUtils);
      eventCuts->AddCut(cutVertex);
      eventCuts->SetCutScheme(Form("%s&%s",cutEventUtils->GetName(),cutVertex->GetName()));
    }else if(cutEventUtils && !cutVertex){
      eventCuts->AddCut(cutEventUtils);
      eventCuts->SetCutScheme(Form("%s",cutEventUtils->GetName()));
    }else if(!cutEventUtils && !cutVertex){
      eventCuts->AddCut(cutVertex);
      eventCuts->SetCutScheme(Form("%s",cutVertex->GetName()));
    }

    task->SetEventCuts(eventCuts);
  }

  // -- EVENT-ONLY COMPUTATIONS -------------------------------------------------------------------

  //vertex
  Int_t vtxID=task->CreateValue(AliRsnMiniValue::kVz,kFALSE);
  AliRsnMiniOutput* outVtx=task->CreateOutput("eventVtx","HIST","EVENT");
  outVtx->AddAxis(vtxID,240,-12.0,12.0);

  //multiplicity or centrality
  Int_t multID=task->CreateValue(AliRsnMiniValue::kMult,kFALSE);
  AliRsnMiniOutput* outMult=task->CreateOutput("eventMult","HIST","EVENT");
  if(isPP && !MultBins) outMult->AddAxis(multID,400,0.5,400.5);
  else outMult->AddAxis(multID,110,0.,110.);

  TH2F* hvz=new TH2F("hVzVsCent","",110,0.,110., 240,-12.0,12.0);
  task->SetEventQAHist("vz",hvz);//plugs this histogram into the fHAEventVz data member

  TH2F* hmc=new TH2F("MultiVsCent","", 110,0.,110., 400,0.5,400.5);
  hmc->GetYaxis()->SetTitle("QUALITY");
  task->SetEventQAHist("multicent",hmc);//plugs this histogram into the fHAEventMultiCent data member

  // -- PAIR CUTS (common to all resonances) ------------------------------------------------------

  AliRsnCutMiniPair* cutY=new AliRsnCutMiniPair("cutRapidity",AliRsnCutMiniPair::kRapidityRange);
  cutY->SetRangeD(minYlab,maxYlab);

  AliRsnCutSet* cutsPair=new AliRsnCutSet("pairCuts",AliRsnTarget::kMother);
  cutsPair->AddCut(cutY);
  cutsPair->SetCutScheme(cutY->GetName());

  // -- CONFIG ANALYSIS --------------------------------------------------------------------------

  gROOT->LoadMacro("$ALICE_PHYSICS/PWGLF/RESONANCES/macros/mini/ConfigPhiPP5TeV_PID.C");
  if(!ConfigPhiPP5TeV_PID(task,isMC,isPP,"",cutsPair,aodFilterBit,customQualityCutsID,cutKaCandidate,nsigmaKa,enableMonitor,isMC&IsMcTrueOnly,monitorOpt.Data(),useMixLS,isMC&checkReflex,yaxisvar,polarizationOpt)) return 0x0;

  // -- CONTAINERS --------------------------------------------------------------------------------

  TString outputFileName = AliAnalysisManager::GetCommonFileName();
  //  outputFileName += ":Rsn";
  Printf("AddAnalysisTaskPhiPP5TeV_PID - Set OutputFileName : \n %s\n",outputFileName.Data());

  AliAnalysisDataContainer* output=mgr->CreateContainer(Form("RsnOut_%s",outNameSuffix.Data()),
							TList::Class(),
							AliAnalysisManager::kOutputContainer,
							outputFileName);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output);

  return task;
}

<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "s3d/robust_estimation/ransac.h"
#include "s3d/robust_estimation/robust_estimation_traits.h"

#include "s3d/multiview/stan_fundamental_matrix_solver.h"

using s3d::Ransac;
using s3d::RansacAlgorithm;

// Ax + By + C = 0
struct Line {
  double A;
  double B;
  double C;
};

// Example for line solver
class LineSolver {
 public:
  using SampleType = double;
  using ModelType = Line;

  static ModelType ComputeModel(const std::vector<SampleType>& x,
                                const std::vector<SampleType>& y) {
    assert(x.size() >= 2);
    assert(y.size() >= 2);

    // distance between pts
    auto dx = x[1] - x[0];
    auto dy = y[1] - y[0];
    auto dNorm = sqrt(dx * dx + dy * dy);

    auto A = -dy / dNorm;
    auto B = dx / dNorm;
    auto C = A * x[0] + B * y[0];
    return {A, B, C};
  }
};

// traits must be in the same namespace
namespace s3d {
template <>
struct robust_solver_traits<LineSolver> {
  using SampleType = LineSolver::SampleType;
  using ModelType = LineSolver::ModelType;
  enum { MIN_NB_SAMPLES = 2 };
};
}  // namespace s3d

// Distance that can be applied to the model
class LeastSquareDistanceFunction {
 public:
  using SampleType = LineSolver::SampleType;

  static void ComputeDistance(const std::vector<SampleType>& x,
                              const std::vector<SampleType>& y,
                              const LineSolver::ModelType& model,
                              std::vector<double>* distances) {
    assert(x.size() == y.size());
    assert(x.size() == distances->size());
    for (size_t i = 0; i < distances->size(); i++) {
      distances->operator[](i) = model.A * x[i] + model.B * y[i] + model.C;
    }
  }
};

TEST(ransac, line_solver) {
  Ransac::Params params{};
  params.nbTrials = 100;
  RansacAlgorithm<LineSolver, LeastSquareDistanceFunction> ransac(params);

  // inliers: y = x
  using SampleType = LineSolver::SampleType;
  auto x = std::vector<SampleType>{0, 1, 2, 3, 4, 5, 6, 7, 8};
  auto y = std::vector<SampleType>{0, 1, 2, 3, 4, 5, 6, 7, 8};

  // outliers
  x.insert(std::end(x), {1, 3, 4, 6, 8});
  y.insert(std::end(y), {5, 6, 1, 1, 3});

  auto line = ransac(x, y);

  EXPECT_DOUBLE_EQ(line.A, -line.B);
  EXPECT_DOUBLE_EQ(line.C, 0);
}

class FakeDistanceAllOverThreshold {
 public:
  using SampleType = LineSolver::SampleType;

  static constexpr auto THRESHOLD = 0.0;

  static void ComputeDistance(const std::vector<SampleType>& x,
                              const std::vector<SampleType>& y,
                              const LineSolver::ModelType& model,
                              std::vector<double>* distances) {
    for (auto i = 0ULL; i < distances->size(); ++i) {
      distances->operator[](i) = THRESHOLD + 1;
    }
  }
};

TEST(ransac, not_enough_inliers_throws) {
  Ransac::Params params{};
  params.nbTrials = 1;
  params.distanceThreshold = FakeDistanceAllOverThreshold::THRESHOLD;
  RansacAlgorithm<LineSolver, LeastSquareDistanceFunction> ransac(params);

  EXPECT_THROW(ransac({0, 0}, {0, 0}), s3d::NotEnoughInliersFound);
}
<commit_msg>Test coverage for ransac updateNbTrials<commit_after>#include "gtest/gtest.h"

#include "s3d/robust_estimation/ransac.h"
#include "s3d/robust_estimation/robust_estimation_traits.h"

#include "s3d/multiview/stan_fundamental_matrix_solver.h"

using s3d::Ransac;
using s3d::RansacAlgorithm;

// Ax + By + C = 0
struct Line {
  double A;
  double B;
  double C;
};

// Example for line solver
class LineSolver {
 public:
  using SampleType = double;
  using ModelType = Line;

  static ModelType ComputeModel(const std::vector<SampleType>& x,
                                const std::vector<SampleType>& y) {
    assert(x.size() >= 2);
    assert(y.size() >= 2);

    // distance between pts
    auto dx = x[1] - x[0];
    auto dy = y[1] - y[0];
    auto dNorm = sqrt(dx * dx + dy * dy);

    auto A = -dy / dNorm;
    auto B = dx / dNorm;
    auto C = A * x[0] + B * y[0];
    return {A, B, C};
  }
};

// traits must be in the same namespace
namespace s3d {
template <>
struct robust_solver_traits<LineSolver> {
  using SampleType = LineSolver::SampleType;
  using ModelType = LineSolver::ModelType;
  enum { MIN_NB_SAMPLES = 2 };
};
}  // namespace s3d

// Distance that can be applied to the model
class LeastSquareDistanceFunction {
 public:
  using SampleType = LineSolver::SampleType;

  static void ComputeDistance(const std::vector<SampleType>& x,
                              const std::vector<SampleType>& y,
                              const LineSolver::ModelType& model,
                              std::vector<double>* distances) {
    assert(x.size() == y.size());
    assert(x.size() == distances->size());
    for (size_t i = 0; i < distances->size(); i++) {
      distances->operator[](i) = model.A * x[i] + model.B * y[i] + model.C;
    }
  }
};

TEST(ransac, line_solver) {
  Ransac::Params params{};
  params.nbTrials = 100;
  RansacAlgorithm<LineSolver, LeastSquareDistanceFunction> ransac(params);

  // inliers: y = x
  using SampleType = LineSolver::SampleType;
  auto x = std::vector<SampleType>{0, 1, 2, 3, 4, 5, 6, 7, 8};
  auto y = std::vector<SampleType>{0, 1, 2, 3, 4, 5, 6, 7, 8};

  // outliers
  x.insert(std::end(x), {1, 3, 4, 6, 8});
  y.insert(std::end(y), {5, 6, 1, 1, 3});

  auto line = ransac(x, y);

  EXPECT_DOUBLE_EQ(line.A, -line.B);
  EXPECT_DOUBLE_EQ(line.C, 0);
}

class FakeDistanceAllOverThreshold {
 public:
  using SampleType = LineSolver::SampleType;

  static constexpr auto THRESHOLD = 0.0;

  static void ComputeDistance(const std::vector<SampleType>& x,
                              const std::vector<SampleType>& y,
                              const LineSolver::ModelType& model,
                              std::vector<double>* distances) {
    for (auto i = 0ULL; i < distances->size(); ++i) {
      distances->operator[](i) = THRESHOLD + 1;
    }
  }
};

TEST(ransac, not_enough_inliers_throws) {
  Ransac::Params params{};
  params.nbTrials = 1;
  params.distanceThreshold = FakeDistanceAllOverThreshold::THRESHOLD;
  RansacAlgorithm<LineSolver, LeastSquareDistanceFunction> ransac(params);

  EXPECT_THROW(ransac({0, 0}, {0, 0}), s3d::NotEnoughInliersFound);
}

TEST(ransac_trials, update_nb_correct) {
  struct RansacForTrials : Ransac {
    bool testUpdateNbTrialsNotReachedMax() {
      Ransac::Trials t(200, 1000, {});
      t.updateNb(199.0);
      return t.reachedMaxNb();
    }
    bool testUpdateNbTrialsReachedMax() {
      Ransac::Trials t(200, 1000, {});
      t.updateNb(200.0);
      return t.reachedMaxNb();
    }
  };

  RansacForTrials t;
  EXPECT_FALSE(t.testUpdateNbTrialsNotReachedMax());
  EXPECT_TRUE(t.testUpdateNbTrialsReachedMax());
}
<|endoftext|>