/*********************************************************************
 * 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.1 $
 *********************************************************************/

#ifndef _KERNEL_H
#define _KERNEL_H

#include <Matrix.h>

namespace prapi
{
	/**
	 * Static methods for creating kernels for various purposes. Kernels
	 * are used by many algorithms that work in a neighborhood defined
	 * by some type of a kernel. Also, binary morphology operations need
	 * structuring elements that can be created by this class.
	 **/
	class Kernel
	{
	public:
		/**
		 * Create a circular kernel of values. The size of the resulting
		 * matrix is (2*radius+1)-by-(2*radius+1). All items in the matrix
		 * whose spatial distance to the center is greater than radius are
		 * set to zero, and the others to the given value.
		 *		 
		 * <pre>
		 * Matrix&lt;int&gt; mat(Kernel::createCircular(2,1));
		 * mat = 0 0 1 0 0
		 *       0 1 1 1 0
		 *       1 1 1 1 1
		 *       0 1 1 1 0
		 *       0 0 1 0 0
		 * </pre>
		 **/
		template <class T> static util::Matrix<T> createCircular(int radius, T value=T(1));

		/**
		 * Create a size-by-size square matrix with all elements set to
		 * the given value. For example:
		 *
		 * <pre>
		 * Matrix&lt;int&gt; mat(Kernel::createSquare(4,3));
		 * mat = 3 3 3 3
		 *       3 3 3 3
		 *       3 3 3 3
		 *       3 3 3 3
		 * </pre>
		 **/
		template <class T> static util::Matrix<T> createSquare(int size, T value=T(1));
	};

	template <class T> util::Matrix<T> Kernel::createCircular(int radius, T value)
	{
		util::Matrix<T> result(radius*2+1);
		for (int x=-radius;x<=radius;x++)
			{
				int rad = (int)(sqrt(radius*radius-x*x)+0.5);
				for (int y=-rad;y<=rad;y++)
					result(y+radius,x+radius) = value;
			}
		return result;
	}
	
	template <class T> util::Matrix<T> Kernel::createSquare(int size, T value)
	{
		Matrix<T> result(size, false);
		result = value;
		return result;
	}

}

#endif
