/*
 * EObject.h
 *
 *  Created on: Jun 25, 2014
 *      Author: Daniel Wesierski
 */

#ifndef EOBJECT_H_
#define EOBJECT_H_

#include "part.h"
#include "grid.h"
#include "helpers.h"
#include <vector>


class EObject   
{
public:
	EObject()
	: scale(1.0), appVar(0), angVar(0), nBins(0) {};	

	EObject(const cv::Mat image, Config& conf)
    : scale(1.0), appVar(conf.appearanceVar), angVar(conf.angularVar), nBins(conf.histNBins) {

		// init parts (must be within image)
		for (unsigned int i=0; i!=conf.initBboxes.size(); ++i) {
			if (conf.initBboxes[i].x < 0 || conf.initBboxes[i].y < 0 ||
				conf.initBboxes[i].x+conf.initBboxes[i].width > image.cols ||
				conf.initBboxes[i].y+conf.initBboxes[i].height > image.rows) {
				throw std::domain_error("Initial BBox not within image range.");
			} else {
				parts.push_back(Part(image, conf.initBboxes[i], nBins));
			}
		}

		// init grids
		for (unsigned int i=0; i!=parts.size(); ++i)
			grids.push_back(Grid(parts[i].bbox, image.cols, image.rows, conf));

		//-- Configuration
		init_chain(conf.partsIdx);
		init_CS();
		init_pose_params_1D();

		draw(image,1);
		show_img(image,true);
		double fff = 0;
	};

	void init_chain(std::vector<std::vector<unsigned int> > partsIdx);
	void init_CS();
	void init_pose_params_1D();
	void init_pose_params_2D();
	void get_orientation();
	void get_orientation_SVD();
	cv::Point2d get_center();
	cv::Mat get_patch(const cv::Mat& image, const cv::Rect roi);
	void draw(cv::Mat image, int opt=2, bool withCS=false, cv::Point ulCorner = cv::Point(0,0), int whatColor=2, int lineWidth=1, int lineType=CV_AA);	
	void draw_seg_CS(cv::Mat& image, cv::Point ulCorner, unsigned int segIdx, int radius, cv::Scalar colorOrient);

	std::vector<Part> parts; // stores all object parts
	std::vector<Grid> grids;  // stores grids, each per part
	std::vector<double> kinMean;	// spatial mean parameters between neighbor parts
	std::vector<double> kinStdDev;  // spatial std deviation parameters between neighbor parts
	std::vector<double> kinAngOff; // angular offsets/means between 'neighbor parts' and corresponding segment orientation
	std::vector<cv::Point2d> segCS; // coordinate system (CS) of each segment (determined by single, oriented vector of e.g. y-axis)
	std::vector<std::vector<unsigned int> > partSegments; // specifies which parts belong to which segments
	double scale;
	double appVar;
	double angVar;
	unsigned int nBins;
};

#endif /* EOBJECT_H_ */
