/*
 *  ofxOpenCvBlob.h
 *  opencv_jni
 *
 *  Created by palimpseste on 12/12/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */




#ifndef _OFX_OPENCV_BLOB
#define _OFX_OPENCV_BLOB


#include "opencv2/core/types_c.h"
#include <vector>







// namespace
using namespace std;



// TODO: use CvRect and CvPoint only for quick conversion
// prefers use ofRectangle and ofPoint instead

// Openframeworks ofxOpenCvBlob object
class ofxOpenCvBlob {
	
	public :
	
	
		float			area;		// the area of the blob in pixels
        float			length;		// the length of the perimeter in pixels
        ofRectangle		rectangle;	// the containing rectangle of the blob
        ofPoint			centroid;	// the centroid or barycenter of the blob
        ofPoint			center;		// the absolute center of the blob rectangle
        bool			isHole;		// is this blob a hole inside of another blob
        vector<ofPoint>	points;		// the list of points defining the shape of the blob

        
        ofxOpenCvBlob() {
		
            area 		= 0.0f;
            length 		= 0.0f;
            isHole 		= false;
			
			points.clear();
        }
		
		#ifdef OF_MAIN
		void draw();
		void draw( ofPoint pt );
		void draw( float x, float y );
		void draw( float x, float y, float width, float height );
		#endif
		
		void scale( float factor );
		void smooth( float value );
		//void rotate( float degree, ofPoint pivot=ofPoint() );
		void translate( float x, float y );
		
	
		
				
	//protected :
	
		// global image size:  Cv dimensions while not scaled
		float pwidth;
		float pheight;
};




// -------------------------------------------------------------------------------------------------
	#pragma mark draw
// -------------------------------------------------------------------------------------------------

// draw() method are only for Openframeworks
// for Procesing, Java will do this job for us
#ifdef OF_MAIN

	// draw blobs shape from top/left corner
	inline void ofxOpenCvBlob::draw() {
		//draw( 0, 0, rectangle.width, rectangle.height );
		draw( 0, 0, pwidth, pheight );
	};

	// draw blobs shape at the given coordinate
	inline void ofxOpenCvBlob::draw( float x, float y ) {
		//draw( x, y, rectangle.width, rectangle.height );
		draw( x, y, pwidth, pheight );
	};

	// draw blobs shape at the given coordinate and specified dimension
	// this method scale blob for preview but not inner shape points definition
	inline void ofxOpenCvBlob::draw( float x, float y, float width, float height ) {

		if ( width==0 && height==0 ) return;

		float px = pwidth==width   ? 1.f : width  / pwidth;
		float py = pheight==height ? 1.f : height / pheight;
		
		//float px = width  / rectangle.width;
		//float py = height / rectangle.height;
		
		ofBeginShape();
		for( vector<ofPoint>::iterator itr=points.begin(); itr!=points.end(); itr++ ) {
			ofVertex( x+(itr->x*px), y+(itr->y*py) );
		}
		ofEndShape( true );
		
	}
	
#endif




// -------------------------------------------------------------------------------------------------
	#pragma mark geometry
// -------------------------------------------------------------------------------------------------

/**
 * Scale blobs shape.
 */
inline void ofxOpenCvBlob::scale( float factor )
{

	if ( factor==1.0 ) return;
	
	pwidth			 *= factor;
	pheight			 *= factor;
	
	centroid.x		 *= factor;
	centroid.y		 *= factor;
	
	rectangle.x		 *= factor;
	rectangle.y		 *= factor;
	rectangle.width  *= factor;
	rectangle.height *= factor;
	
	center.x		  = rectangle.x+(rectangle.width/2);
	center.y		  = rectangle.y+(rectangle.height/2);
	
	for( vector<ofPoint>::iterator itr=points.begin(); itr!=points.end(); itr++ ) {
		itr->x *=factor;
		itr->y *=factor;
	}
}


/**
 * Rotate blobs shape.
 *
inline void ofxOpenCvBlob::rotate( float degree, ofPoint pivot )
{

	if ( degree==0.0 || degree==360.0 ) return;
	
	ofPoint pt;
	
	centroid.rotate( degree, pivot );
	center.rotate( degree, pivot );
	
	//rectangle.x		 *= value;
	//rectangle.y		 *= value;
	//rectangle.width  *= value;
	//rectangle.height *= value;
	
	vector<ofPoint>::iterator itr = points.begin();
	while( itr!=points.end() ) {
		if ( pivot==pt ) (*itr++).rotate( degree );
		else (*itr++).rotate( degree, pivot );
	}
}*/


/**
 * Translate blobs shape to the given point
 * TODO: center
 */
inline void ofxOpenCvBlob::translate( float x, float y )
{
	centroid.x	+= x;
	centroid.y	+= y;
	center.x	+= y;
	center.y	+= x;
	rectangle.x	+= x;
	rectangle.y	+= y;
	
	for( vector<ofPoint>::iterator itr=points.begin(); itr!=points.end(); itr++ ) {
		itr->x +=x;
		itr->y +=y;
	}
}



	
// -------------------------------------------------------------------------------------------------
	#pragma mark transform
// -------------------------------------------------------------------------------------------------

/**
 * Smooth blobs shape.
 */
inline void ofxOpenCvBlob::smooth( float value )
{

	if ( value==1.0 ) return;
	

	int cnt = points.size();
	float inv = 1.0 - value;
	
	for( int i=1; i<cnt; i++ ) {
		points[i].x *= value;
		points[i].y *= value;
		points[i].x += points[i-1].x * inv;
		points[i].y += points[i-1].y * inv;
	}
}


#endif
