/*********************************************************************
 * This file is part of the PRAPI library.
 *
 * Copyright (C) 2002 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.3 $
 *********************************************************************/

#ifndef _COMPONENT_H
#define _COMPONENT_H

namespace prapi { namespace binary {

	/**
	 * The Component class stores information about connected (binary)
	 * components. It also contains static methods for extracting
	 * component information from labeled images.
	 **/
	class Component
	{
	public:
		/**
		 * Create a new component with the given center of mass row and
		 * column coordinates, mass, and label index.
		 **/
		Component(double r=0, double c=0, int m=0, int index=0) :
			comR(r), comC(c), mass(m), labelIndex(index) {}

		/**
		 * The copy constructor.
		 **/
		Component(const Component& other) :
			comR(other.comR), comC(other.comC), mass(other.mass), labelIndex(other.labelIndex) {}

		/**
		 * Assignment operator.
		 **/
		Component& operator= (const Component& other)
		{
			comR = other.comR;
			comC = other.comC;
			mass = other.mass;
			labelIndex = other.labelIndex;
		}

		/**
		 * Compare two components. Two components compare the same if
		 * their masses match.
		 **/
		bool operator== (const Component& other) const { return mass == other.mass; }
		/**
		 * Compare components according to their masses.
		 **/
		bool operator!= (const Component& other) const { return mass != other.mass; }
		/**
		 * Compare components according to their masses.
		 **/
		bool operator< (const Component& other) const { return mass < other.mass; }
		/**
		 * Compare components according to their masses.
		 **/
		bool operator> (const Component& other) const { return mass > other.mass; }
		/**
		 * Compare components according to their masses.
		 **/
		bool operator>= (const Component& other) const { return mass >= other.mass; }
		/**
		 * Compare components according to their masses.
		 **/
		bool operator<= (const Component& other) const { return mass <= other.mass; }
		
		/**
		 * The row coordinate of the center of mass of an object.
		 **/
		double comR;
		/**
		 * The column coordinate of the center of mass of an object.
		 **/
		double comC;
		/**
		 * The number of pixels in the connected component.
		 **/
		int mass;

		/**
		 * The index of the component's label in a labeled image.
		 **/
		int labelIndex;

		/**
		 * Get the parameters of a connected component in a labeled image. 
		 * The coordinates and mass of the object with the given label
		 * index are returned. If the label image does not contain such
		 * index, a component with zero mass is returned.
		 *
		 * @param labels an image with connected component labels.
		 * @param index the index of the component to be retrieved.
		 * @return component parameters
		 **/
		static Component getComponent(const util::Matrix<int>& labels, int index);

		/**
		 * Get the parameters of all connected components in a labeled
		 * image. The first item in the returned list stores the
		 * parameters of the component labeled with one, the second one
		 * the parameters of the component labeled with two and so on, up
		 * to the maximum value in the image.
		 *
		 * @param labels an image with connected component labels.
		 * @return the parameters of all connected components
		 **/
		static util::List<Component> getComponents(const util::Matrix<int>& labels);
	};
}}

#endif
