head	1.9;
access;
symbols
	bobbase:1.9
	bob:1.9.1
	r2_1:1.7
	r2_0:1.6
	r1_1_beta:1.5
	r1_1_alpha:1.4
	r1_0:1.4
	r0_11:1.3
	r0_10:1.1;
locks
	thoth:1.9.1.3; strict;
comment	@// @;


1.9
date	94.12.22.17.37.10;	author fjsoria;	state Exp;
branches
	1.9.1.1;
next	1.8;

1.8
date	94.12.22.16.27.20;	author fjsoria;	state Exp;
branches;
next	1.7;

1.7
date	94.09.16.14.57.11;	author thoth;	state Exp;
branches;
next	1.6;

1.6
date	94.08.22.15.20.29;	author thoth;	state Exp;
branches;
next	1.5;

1.5
date	94.07.25.17.26.39;	author thoth;	state Exp;
branches;
next	1.4;

1.4
date	94.05.08.19.40.25;	author thoth;	state Exp;
branches;
next	1.3;

1.3
date	94.04.15.13.17.10;	author thoth;	state Exp;
branches;
next	1.2;

1.2
date	94.03.30.13.56.46;	author thoth;	state Exp;
branches;
next	1.1;

1.1
date	94.01.31.16.43.38;	author thoth;	state Exp;
branches;
next	;

1.9.1.1
date	94.12.28.18.22.11;	author thoth;	state Exp;
branches;
next	1.9.1.2;

1.9.1.2
date	95.01.09.18.08.04;	author thoth;	state Exp;
branches;
next	1.9.1.3;

1.9.1.3
date	95.01.13.19.37.42;	author thoth;	state Exp;
branches;
next	;


desc
@Container class for the point->pointset mapping, known as
a neighborhood.  Used for reductions (like a template product,
but no circle operation, just a gamma).
@


1.9
log
@removed static data memeber template for double nbh.
@
text
@// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//


//
// $Log: Nbh.c,v $
// Revision 1.8  1994/12/22  16:27:20  fjsoria
// static data member template problem fixed for g++
//
// Revision 1.7  1994/09/16  14:57:11  thoth
// more DOS-inspired renaming.
//
// Revision 1.6  1994/08/22  15:20:29  thoth
// DOS-inspired name rework.
//
// Revision 1.5  1994/07/25  17:26:39  thoth
// Name sanitization
//
// Revision 1.4  1994/05/08  19:40:25  thoth
// New automatic neighborhood decomposition capability.
//
// Revision 1.3  1994/04/15  13:17:10  thoth
// Finish up the list of generic reductions.
//
// Revision 1.2  1994/03/30  13:56:46  thoth
// generic neighborhood reductions are now available.
//
// Revision 1.1  1994/01/31  16:43:38  thoth
// Initial revision
//

#include	<values.h>

#include "Image.h"
#include "ImageIter.h"
#include "VectorI.h"
#include "PSIter.h"

#include "Nbh.h"
#include "InvNbh.h"

template <class P, class Q>
void IA_Neighborhood<P,Q>::set_and_reference(IA_BaseNbh<P,Q> *p)
{
  p->incr_ref();
  bnbh = p;
}

template <class P, class Q>
void IA_Neighborhood<P,Q>::disassociate()
{
  if (bnbh->decr_ref() <= 0)
    delete bnbh;
  bnbh = 0;
}

#ifndef IA_NO_AUTOINST_OF_STATIC_DATA
template <class P, class Q>
int IA_Neighborhood<P,Q>::auto_decomposition=1;
#else
int IA_Neighborhood<IA_Point<int>,IA_Point<int> >::auto_decomposition=1;
// double nieghborhoods not implemented yet
//int IA_Neighborhood<IA_Point<double>,IA_Point<double> >::auto_decomposition=1;
#endif


template <class P, class Q>
IA_Neighborhood<P,Q>::IA_Neighborhood(const IA_Neighborhood<P,Q> &arg)
{
    set_and_reference(arg.bnbh);
}


template <class P, class Q>
IA_Neighborhood<P,Q>::IA_Neighborhood(unsigned dim, const IA_Set<P> &ps)
{
    set_and_reference
      (new IA_InvariantNbh<P,Q>(IA_Set<Q>::WhiteHole(dim), ps));
}

template <class P, class Q>
IA_Neighborhood<P,Q>::~IA_Neighborhood()
{
  disassociate();
}

template <class P, class Q>
IA_Neighborhood<P,Q>& IA_Neighborhood<P,Q>::operator=
	(const IA_Neighborhood<P,Q> &arg)
{
  IA_BaseNbh<P,Q>	*temp = arg.bnbh;
  temp->incr_ref();

  disassociate();

  bnbh = temp;

  return *this;
}

#include "NbhOps.c"

//
// Generic backward neighborhood reduction
//

template <class T>
IA_Image<IA_Point<int>, T> backw_nbh_inv_core1
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];

    {
	int	*o_scan = nbh_offsets;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	IA_Point<int>	ip;
	while (iter(ip)) {
	    *o_scan = ip[0];
	    for (unsigned i=1; i<dimen; i++) {
		*o_scan *= src_width[i];
		*o_scan += ip[i];
	    }
	    o_scan++;
	}
    }

    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    T *const	dest_data = new T[dest_ps.card()];
    T *	valp = dest_data;

    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	*valp = gamma_zero;
	for (i=0; i<nbh_sz; i++) {
	    *valp = gamma(base[nbh_offsets[i]], *valp);
	}
	valp++;
    }
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,T>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class T>
IA_Image<IA_Point<int>, T> backw_nbh_inv1
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    IA_Point<int>	inf_ = dest_ps.inf()+invnbh.inf();
    IA_Point<int>	sup_ = dest_ps.sup()+invnbh.sup();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];

    zero_extend(img, src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,T>	rval =
	backw_nbh_inv_core1(inf_, sup_-inf_ + 1, src_data, invnbh, dest_ps,
			    gamma, gamma_zero);

    delete[] src_data;

    return rval;
}

template <class T>
IA_Image<IA_Point<int>,T> neighborhood_reduction
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return backw_nbh_inv1
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, T, T>::extract_baseptr(nbh))->value,
	     dest_ps, gamma, gamma_zero);
    } else {
	T *const	dest_data = new T[dest_ps.card()];
	T	*valp = dest_data;
	IA_PSIter<IA_Point<int> >	dest_iter(dest_ps);
	IA_Point<int>	base_ip;
	while (dest_iter(base_ip)) {
	    IA_Set<IA_Point<int> >	ps = nbh(base_ip);

	    IA_PSIter<IA_Point<int> >	nbh_iter(ps);
	    IA_Point<int>	nbh_ip;

	    *valp = gamma_zero;

	    while ( nbh_iter(nbh_ip) ) {
		if (! img.domain().contains(nbh_ip))
		    continue;
		*valp = gamma(img(nbh_ip), *valp);
	    }
	    valp++;
	}
	return IA_Image<IA_Point<int>,T>(dest_ps, dest_data,
					   dest_ps.card(), 1);
    }
}

//
// Generic backward neighborhood reduction
//

template <class S, class T>
IA_Image<IA_Point<int>, S> backw_nbh_inv_core
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];

    {
	int	*o_scan = nbh_offsets;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	IA_Point<int>	ip;
	while (iter(ip)) {
	    *o_scan = ip[0];
	    for (unsigned i=1; i<dimen; i++) {
		*o_scan *= src_width[i];
		*o_scan += ip[i];
	    }
	    o_scan++;
	}
    }

    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    S *const	dest_data = new S[dest_ps.card()];
    S *	valp = dest_data;
    T	*a = new T[nbh_sz];
    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	for (i=0; i<nbh_sz; i++) {
	    a[i] = base[nbh_offsets[i]];
	}
	*(valp++) = Gamma(a, nbh_sz);
    }
    delete[] a;
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,S>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class S, class T>
IA_Image<IA_Point<int>, S> backw_nbh_inv
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 T gamma_zero,
 const S*)
{
    IA_Point<int>	inf_ = dest_ps.inf()+invnbh.inf();
    IA_Point<int>	sup_ = dest_ps.sup()+invnbh.sup();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];

    zero_extend(img, src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,S>	rval =
	backw_nbh_inv_core(inf_, sup_-inf_ + 1, src_data, invnbh, dest_ps,
			   Gamma, (S*)0);

    delete[] src_data;

    return rval;
}

template <class S, class T>
IA_Image<IA_Point<int>,S> neighborhood_reduction
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T gamma_zero,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return backw_nbh_inv
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, S, T>::extract_baseptr(nbh))->value,
	     dest_ps, Gamma, gamma_zero, (const S*)0);
    } else {
	S *const	dest_data = new S[dest_ps.card()];
	S	*valp = dest_data;
	IA_PSIter<IA_Point<int> >	dest_iter(dest_ps);
	IA_Point<int>	base_ip;
	while (dest_iter(base_ip)) {
	    IA_Set<IA_Point<int> >	ps = nbh(base_ip);

	    IA_PSIter<IA_Point<int> >	nbh_iter(ps);
	    IA_Point<int>	nbh_ip;

	    T	*const a = new T[ps.card()];
	    unsigned	count=0;

	    while ( nbh_iter(nbh_ip) ) {
		if (! img.domain().contains(nbh_ip))
		    continue;
		a[count++] = img(nbh_ip);
	    }
	    *(valp++) = Gamma(a, count);
	    delete[] a;
	}
	return IA_Image<IA_Point<int>,S>(dest_ps, dest_data,
					   dest_ps.card(), 1);
    }
}

//
// Generic backward neighborhood reduction
//

template <class S, class T>
IA_Image<IA_Point<int>, S> backw_nbh_inv_core3
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &src_ps,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];
    IA_Point<int>	*nbh_points = new IA_Point<int>[nbh_sz];

    {
	int	j;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	for (j=0; iter(nbh_points[j]); j++) {
	    nbh_offsets[j] = nbh_points[j][0];
	    for (unsigned i=1; i<dimen; i++) {
		nbh_offsets[j] *= src_width[i];
		nbh_offsets[j] += nbh_points[j][i];
	    }
	}
    }

    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    S *const	dest_data = new S[dest_ps.card()];
    S *	valp = dest_data;
    T	*a = new T[nbh_sz];
    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	unsigned count=0;
	for (i=0; i<nbh_sz; i++) {
	    if (src_ps.contains(ip+nbh_points[i]))
		a[count++] = base[nbh_offsets[i]];
	}
	*(valp++) = Gamma(a, count);
    }
    delete[] a;
    delete[] nbh_points;
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,S>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class S, class T>
IA_Image<IA_Point<int>, S> backw_nbh_inv3
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    IA_Point<int>	inf_ = dest_ps.inf()+invnbh.inf();
    IA_Point<int>	sup_ = dest_ps.sup()+invnbh.sup();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];
    T	gamma_zero;		// whatever

    zero_extend(img, src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,S>	rval =
	backw_nbh_inv_core3(inf_, sup_-inf_ + 1, src_data, img.domain(),
			    invnbh, dest_ps,
			    Gamma, (S*)0);

    delete[] src_data;

    return rval;
}

template <class S, class T>
IA_Image<IA_Point<int>,S> neighborhood_reduction
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return backw_nbh_inv3
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, S, T>::extract_baseptr(nbh))->value,
	     dest_ps, Gamma, (const S*)0);
    } else {
	S *const	dest_data = new S[dest_ps.card()];
	S	*valp = dest_data;
	IA_PSIter<IA_Point<int> >	dest_iter(dest_ps);
	IA_Point<int>	base_ip;
	while (dest_iter(base_ip)) {
	    IA_Set<IA_Point<int> >	ps = nbh(base_ip);

	    IA_PSIter<IA_Point<int> >	nbh_iter(ps);
	    IA_Point<int>	nbh_ip;

	    T	*const a = new T[ps.card()];
	    unsigned	count=0;

	    while ( nbh_iter(nbh_ip) ) {
		if (! img.domain().contains(nbh_ip))
		    continue;
		a[count++] = img(nbh_ip);
	    }
	    *(valp++) = Gamma(a, count);
	    delete[] a;
	}
	return IA_Image<IA_Point<int>,S>(dest_ps, dest_data,
					   dest_ps.card(), 1);
    }
}

//
// Generic forward neighborhood reduction
//

template <class T>
IA_Image<IA_Point<int>, T> forw_nbh_inv_core1
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];

    {
	int	*o_scan = nbh_offsets;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	IA_Point<int>	ip;
	while (iter(ip)) {
	    *o_scan = -ip[0];
	    for (unsigned i=1; i<dimen; i++) {
		*o_scan *= src_width[i];
		*o_scan -= ip[i];
	    }
	    o_scan++;
	}
    }

    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    T *const	dest_data = new T[dest_ps.card()];
    T *	valp = dest_data;

    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	*valp = gamma_zero;
	for (i=0; i<nbh_sz; i++) {
	    *valp = gamma(base[nbh_offsets[i]], *valp);
	}
	valp++;
    }
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,T>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class T>
IA_Image<IA_Point<int>, T> forw_nbh_inv1
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    IA_Point<int>	inf_ = dest_ps.inf()-invnbh.sup();
    IA_Point<int>	sup_ = dest_ps.sup()-invnbh.inf();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];

    zero_extend(img, src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,T>	rval =
	forw_nbh_inv_core1(inf_, sup_-inf_ + 1, src_data, invnbh, dest_ps,
			    gamma, gamma_zero);

    delete[] src_data;

    return rval;
}

template <class T>
IA_Image<IA_Point<int>,T> neighborhood_reduction
(const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &dest_ps,
 T (*gamma)(T, T),
 T gamma_zero)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return forw_nbh_inv1
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, T, T>::extract_baseptr(nbh))->value,
	     dest_ps, gamma, gamma_zero);
    } else {
	unsigned	size = dest_ps.card();
	T *const	dest_data = new T[size];

	for (int i=0; i<size; i++) {
	    dest_data[i] = gamma_zero;
	}

	IA_PSIter<IA_Point<int> >	src_iter(img.domain());
	IA_Point<int>	base_ip;
	while (src_iter(base_ip)) {
	    IA_Set<IA_Point<int> >	ps = nbh(base_ip);

	    IA_PSIter<IA_Point<int> >	nbh_iter(ps);
	    IA_Point<int>	nbh_ip;
	    T	ival = img(base_ip);

	    while ( nbh_iter(nbh_ip) ) {
		if (! dest_ps.contains(nbh_ip))
		    continue;
		unsigned offset = dest_ps.index(nbh_ip);
		dest_data[offset] = gamma(ival, dest_data[offset]);
	    }
	}
	return IA_Image<IA_Point<int>,T>(dest_ps, dest_data,
				       dest_ps.card(), 1);
    }
}

//
// Generic forward neighborhood reduction
//

template <class S, class T>
IA_Image<IA_Point<int>, S> forw_nbh_inv_core
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];

    {
	int	*o_scan = nbh_offsets;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	IA_Point<int>	ip;
	while (iter(ip)) {
	    *o_scan = -ip[0];
	    for (unsigned i=1; i<dimen; i++) {
		*o_scan *= src_width[i];
		*o_scan -= ip[i];
	    }
	    o_scan++;
	}
    }

    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    S *const	dest_data = new S[dest_ps.card()];
    S *	valp = dest_data;
    T	*a = new T[nbh_sz];
    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	for (i=0; i<nbh_sz; i++) {
	    a[i] = base[nbh_offsets[i]];
	}
	*(valp++) = Gamma(a, nbh_sz);
    }
    delete[] a;
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,S>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class S, class T>
IA_Image<IA_Point<int>, S> forw_nbh_inv
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 T gamma_zero,
 const S*)
{
    IA_Point<int>	inf_ = dest_ps.inf()-invnbh.sup();
    IA_Point<int>	sup_ = dest_ps.sup()-invnbh.inf();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];

    zero_extend(IA_Image<IA_Point<int>,T>(img), src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,S>	rval =
	forw_nbh_inv_core(inf_, sup_-inf_ + 1, src_data, invnbh, dest_ps,
			   Gamma, (S*)0);

    delete[] src_data;

    return rval;
}

template <class S, class T>
IA_Image<IA_Point<int>,S> neighborhood_reduction
(const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &dest_ps,
 T gamma_zero,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return forw_nbh_inv
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, S, T>::extract_baseptr(nbh))->value,
	     dest_ps, Gamma, gamma_zero, (const S*)0);
    } else {
	IA::not_yet_implemented(__FILE__,__LINE__);
    }
}

//
// Generic forward neighborhood reduction
//

template <class S, class T>
IA_Image<IA_Point<int>, S> forw_nbh_inv_core3
(IA_Point<int> src_infimum,
 IA_Point<int> src_width,
 const T* src_data,
 const IA_Set<IA_Point<int> > &src_ps,
 const IA_Set<IA_Point<int> > &nbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    const int	dimen = src_width.dim();

    int		nbh_sz = nbh.card();
    int	*const nbh_offsets = new int[nbh_sz];
    IA_Point<int>	*nbh_points = new IA_Point<int>[nbh_sz];

    {
	int	j;
	IA_PSIter<IA_Point<int> >	iter(nbh);
	for (j=0; iter(nbh_points[j]); j++) {
	    nbh_offsets[j] = -nbh_points[j][0];
	    for (unsigned i=1; i<dimen; i++) {
		nbh_offsets[j] *= src_width[i];
		nbh_offsets[j] -= nbh_points[j][i];
	    }
	}
    }


    IA_PSIter<IA_Point<int> >	iter(dest_ps);
    IA_Point<int>	ip;
    S *const	dest_data = new S[dest_ps.card()];
    S *	valp = dest_data;
    T	*a = new T[nbh_sz];
    while (iter(ip)) {
	int	offset= ip[0] - src_infimum[0];
	unsigned i;
	for (i=1; i<dimen; i++) {
	    offset *= src_width[i];
	    offset += ip[i] - src_infimum[i];
	}
	const T *const base = src_data + offset;

	unsigned count=0;
	for (i=0; i<nbh_sz; i++) {
	    if (src_ps.contains(ip - nbh_points[i]))
		a[count++] = base[nbh_offsets[i]];
	}
	*(valp++) = Gamma(a, count);
    }
    delete[] a;
    delete[] nbh_points;
    delete[] nbh_offsets;

    return IA_Image<IA_Point<int>,S>(dest_ps, dest_data, dest_ps.card(), 1);
}


template <class S, class T>
IA_Image<IA_Point<int>, S> forw_nbh_inv3
(const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &invnbh,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    IA_Point<int>	inf_ = dest_ps.inf()-invnbh.sup();
    IA_Point<int>	sup_ = dest_ps.sup()-invnbh.inf();
    IA_Set<IA_Point<int> >	src_ps = IA_Set<IA_Point<int> >(inf_,sup_);

    T	*const src_data = new T[src_ps.card()];

    T	gamma_zero;
    zero_extend(img, src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_Point<int>,S>	rval =
	forw_nbh_inv_core3(inf_, sup_-inf_ + 1, src_data, img.domain(),
			   invnbh, dest_ps,
			   Gamma, (S*)0);

    delete[] src_data;

    return rval;
}

template <class S, class T>
IA_Image<IA_Point<int>,S> neighborhood_reduction
(const IA_Neighborhood<IA_Point<int>,IA_Point<int> > &nbh,
 const IA_CoreImage<IA_Point<int>, T> &img,
 const IA_Set<IA_Point<int> > &dest_ps,
 S (*Gamma)(T*, unsigned count),
 const S*)
{
    if (nbh.type() == IA_InvariantNbh<IA_Point<int>,IA_Point<int> >::s_type()) {
	return forw_nbh_inv3
	    (img,
	     ((IA_InvariantNbh<IA_Point<int>,IA_Point<int> >*) IA_FBI<IA_Point<int>,IA_Point<int>, T, S, T>::extract_baseptr(nbh))->value,
	     dest_ps, Gamma, (const S*)0);
    } else {
	IA::not_yet_implemented(__FILE__,__LINE__);
    }
}
@


1.9.1.1
log
@New Closure and Function Nbh constructors.
@
text
@a10 3
// Revision 1.9  1994/12/22  17:37:10  fjsoria
// removed static data memeber template for double nbh.
//
a44 4
#include "ClosureNbh.h"
#include "FuncNbh.h"

#include "image_errors.h"
a82 19
}


template <class P, class Q>
IA_Neighborhood<P,Q>::IA_Neighborhood(const IA_ClosureNbh<P,Q> &cl)
{
    set_and_reference (cl.clone_self());
}

template <class P, class Q>
IA_Neighborhood<P,Q>::IA_Neighborhood(const IA_Set<Q> &s, IA_Set<P>(*f)(Q))
{
    set_and_reference (new IA_FunctionNbh<P,Q>(s, f));
}

template <class P, class Q>
IA_Neighborhood<P,Q>::IA_Neighborhood(const IA_Set<Q> &s, IA_Set<P>(*f)(const Q&))
{
    set_and_reference (new IA_FunctionRefNbh<P,Q>(s, f));
@


1.9.1.2
log
@Boxy pointset constructor replaced by function.
@
text
@a10 3
// Revision 1.9.1.1  1994/12/28  18:22:11  thoth
// New Closure and Function Nbh constructors.
//
d202 1
a202 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
d324 1
a324 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
d451 1
a451 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
d576 1
a576 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
d702 1
a702 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
d808 1
a808 1
    IA_Set<IA_Point<int> >	src_ps = IA_boxy_pset(inf_,sup_);
@


1.9.1.3
log
@CoreImage has been re-merged with Image.  All special stuff should be
friends of FBI now.
@
text
@a10 3
// Revision 1.9.1.2  1995/01/09  18:08:04  thoth
// Boxy pointset constructor replaced by function.
//
d197 1
a197 1
(const IA_Image<IA_Point<int>, T> &img,
d221 1
a221 1
(const IA_Image<IA_Point<int>, T> &img,
d318 1
a318 1
(const IA_Image<IA_Point<int>, T> &img,
d343 1
a343 1
(const IA_Image<IA_Point<int>, T> &img,
d446 1
a446 1
(const IA_Image<IA_Point<int>, T> &img,
d472 1
a472 1
(const IA_Image<IA_Point<int>, T> &img,
d571 1
a571 1
(const IA_Image<IA_Point<int>, T> &img,
d596 1
a596 1
 const IA_Image<IA_Point<int>, T> &img,
d696 1
a696 1
(const IA_Image<IA_Point<int>, T> &img,
d722 1
a722 1
 const IA_Image<IA_Point<int>, T> &img,
d803 1
a803 1
(const IA_Image<IA_Point<int>, T> &img,
d830 1
a830 1
 const IA_Image<IA_Point<int>, T> &img,
@


1.8
log
@static data member template problem fixed for g++
@
text
@d11 3
d66 2
a67 1
int IA_Neighborhood<IA_Point<double>,IA_Point<double> >::auto_decomposition=1;
@


1.7
log
@more DOS-inspired renaming.
@
text
@d11 3
d58 1
d61 5
@


1.6
log
@DOS-inspired name rework.
@
text
@d11 3
d38 1
a38 1
#include "InvariantNbh.h"
@


1.5
log
@Name sanitization
@
text
@d10 4
a13 1
// $Log: Neighborhood.c,v $
d34 1
a34 1
#include "Neighborhood.h"
d89 1
a89 1
#include "NeighborhoodOps.c"
@


1.4
log
@New automatic neighborhood decomposition capability.
@
text
@d11 3
d93 3
a95 3
IA_Image<IA_IntPoint, T> backw_nbh_inv_core1
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d97 2
a98 2
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d109 2
a110 2
	IA_PSIter<IA_IntPoint>	iter(nbh);
	IA_IntPoint	ip;
d121 2
a122 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d143 1
a143 1
    return IA_Image<IA_IntPoint,T>(dest_ps, dest_data, dest_ps.card(), 1);
d148 4
a151 4
IA_Image<IA_IntPoint, T> backw_nbh_inv1
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d155 3
a157 3
    IA_IntPoint	inf_ = dest_ps.inf()+invnbh.inf();
    IA_IntPoint	sup_ = dest_ps.sup()+invnbh.sup();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d162 1
a162 1
    IA_Image<IA_IntPoint,T>	rval =
d172 4
a175 4
IA_Image<IA_IntPoint,T> neighborhood_reduction
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d179 1
a179 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d182 1
a182 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, T, T>::extract_baseptr(nbh))->value,
d187 2
a188 2
	IA_PSIter<IA_IntPoint>	dest_iter(dest_ps);
	IA_IntPoint	base_ip;
d190 1
a190 1
	    IA_IntPointSet	ps = nbh(base_ip);
d192 2
a193 2
	    IA_PSIter<IA_IntPoint>	nbh_iter(ps);
	    IA_IntPoint	nbh_ip;
d204 1
a204 1
	return IA_Image<IA_IntPoint,T>(dest_ps, dest_data,
d214 3
a216 3
IA_Image<IA_IntPoint, S> backw_nbh_inv_core
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d218 2
a219 2
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d230 2
a231 2
	IA_PSIter<IA_IntPoint>	iter(nbh);
	IA_IntPoint	ip;
d242 2
a243 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d264 1
a264 1
    return IA_Image<IA_IntPoint,S>(dest_ps, dest_data, dest_ps.card(), 1);
d269 4
a272 4
IA_Image<IA_IntPoint, S> backw_nbh_inv
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d277 3
a279 3
    IA_IntPoint	inf_ = dest_ps.inf()+invnbh.inf();
    IA_IntPoint	sup_ = dest_ps.sup()+invnbh.sup();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d284 1
a284 1
    IA_Image<IA_IntPoint,S>	rval =
d294 4
a297 4
IA_Image<IA_IntPoint,S> neighborhood_reduction
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d302 1
a302 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d305 1
a305 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, S, T>::extract_baseptr(nbh))->value,
d310 2
a311 2
	IA_PSIter<IA_IntPoint>	dest_iter(dest_ps);
	IA_IntPoint	base_ip;
d313 1
a313 1
	    IA_IntPointSet	ps = nbh(base_ip);
d315 2
a316 2
	    IA_PSIter<IA_IntPoint>	nbh_iter(ps);
	    IA_IntPoint	nbh_ip;
d329 1
a329 1
	return IA_Image<IA_IntPoint,S>(dest_ps, dest_data,
d339 3
a341 3
IA_Image<IA_IntPoint, S> backw_nbh_inv_core3
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d343 3
a345 3
 const IA_Set<IA_IntPoint> &src_ps,
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d353 1
a353 1
    IA_IntPoint	*nbh_points = new IA_IntPoint[nbh_sz];
d357 1
a357 1
	IA_PSIter<IA_IntPoint>	iter(nbh);
d367 2
a368 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d392 1
a392 1
    return IA_Image<IA_IntPoint,S>(dest_ps, dest_data, dest_ps.card(), 1);
d397 4
a400 4
IA_Image<IA_IntPoint, S> backw_nbh_inv3
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d404 3
a406 3
    IA_IntPoint	inf_ = dest_ps.inf()+invnbh.inf();
    IA_IntPoint	sup_ = dest_ps.sup()+invnbh.sup();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d412 1
a412 1
    IA_Image<IA_IntPoint,S>	rval =
d423 4
a426 4
IA_Image<IA_IntPoint,S> neighborhood_reduction
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d430 1
a430 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d433 1
a433 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, S, T>::extract_baseptr(nbh))->value,
d438 2
a439 2
	IA_PSIter<IA_IntPoint>	dest_iter(dest_ps);
	IA_IntPoint	base_ip;
d441 1
a441 1
	    IA_IntPointSet	ps = nbh(base_ip);
d443 2
a444 2
	    IA_PSIter<IA_IntPoint>	nbh_iter(ps);
	    IA_IntPoint	nbh_ip;
d457 1
a457 1
	return IA_Image<IA_IntPoint,S>(dest_ps, dest_data,
d467 3
a469 3
IA_Image<IA_IntPoint, T> forw_nbh_inv_core1
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d471 2
a472 2
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d483 2
a484 2
	IA_PSIter<IA_IntPoint>	iter(nbh);
	IA_IntPoint	ip;
d495 2
a496 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d517 1
a517 1
    return IA_Image<IA_IntPoint,T>(dest_ps, dest_data, dest_ps.card(), 1);
d522 4
a525 4
IA_Image<IA_IntPoint, T> forw_nbh_inv1
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d529 3
a531 3
    IA_IntPoint	inf_ = dest_ps.inf()-invnbh.sup();
    IA_IntPoint	sup_ = dest_ps.sup()-invnbh.inf();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d536 1
a536 1
    IA_Image<IA_IntPoint,T>	rval =
d546 4
a549 4
IA_Image<IA_IntPoint,T> neighborhood_reduction
(const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_IntPointSet &dest_ps,
d553 1
a553 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d556 1
a556 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, T, T>::extract_baseptr(nbh))->value,
d566 2
a567 2
	IA_PSIter<IA_IntPoint>	src_iter(img.domain());
	IA_IntPoint	base_ip;
d569 1
a569 1
	    IA_IntPointSet	ps = nbh(base_ip);
d571 2
a572 2
	    IA_PSIter<IA_IntPoint>	nbh_iter(ps);
	    IA_IntPoint	nbh_ip;
d582 1
a582 1
	return IA_Image<IA_IntPoint,T>(dest_ps, dest_data,
d592 3
a594 3
IA_Image<IA_IntPoint, S> forw_nbh_inv_core
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d596 2
a597 2
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d608 2
a609 2
	IA_PSIter<IA_IntPoint>	iter(nbh);
	IA_IntPoint	ip;
d620 2
a621 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d642 1
a642 1
    return IA_Image<IA_IntPoint,S>(dest_ps, dest_data, dest_ps.card(), 1);
d647 4
a650 4
IA_Image<IA_IntPoint, S> forw_nbh_inv
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d655 3
a657 3
    IA_IntPoint	inf_ = dest_ps.inf()-invnbh.sup();
    IA_IntPoint	sup_ = dest_ps.sup()-invnbh.inf();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d661 2
a662 2
    zero_extend(IA_Image<IA_IntPoint,T>(img), src_ps, (T*)src_data, gamma_zero);
    IA_Image<IA_IntPoint,S>	rval =
d672 4
a675 4
IA_Image<IA_IntPoint,S> neighborhood_reduction
(const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_IntPointSet &dest_ps,
d680 1
a680 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d683 1
a683 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, S, T>::extract_baseptr(nbh))->value,
d695 3
a697 3
IA_Image<IA_IntPoint, S> forw_nbh_inv_core3
(IA_IntPoint src_infimum,
 IA_IntPoint src_width,
d699 3
a701 3
 const IA_Set<IA_IntPoint> &src_ps,
 const IA_Set<IA_IntPoint> &nbh,
 const IA_IntPointSet &dest_ps,
d709 1
a709 1
    IA_IntPoint	*nbh_points = new IA_IntPoint[nbh_sz];
d713 1
a713 1
	IA_PSIter<IA_IntPoint>	iter(nbh);
d724 2
a725 2
    IA_PSIter<IA_IntPoint>	iter(dest_ps);
    IA_IntPoint	ip;
d749 1
a749 1
    return IA_Image<IA_IntPoint,S>(dest_ps, dest_data, dest_ps.card(), 1);
d754 4
a757 4
IA_Image<IA_IntPoint, S> forw_nbh_inv3
(const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_Set<IA_IntPoint> &invnbh,
 const IA_IntPointSet &dest_ps,
d761 3
a763 3
    IA_IntPoint	inf_ = dest_ps.inf()-invnbh.sup();
    IA_IntPoint	sup_ = dest_ps.sup()-invnbh.inf();
    IA_IntPointSet	src_ps = IA_IntPointSet(inf_,sup_);
d769 1
a769 1
    IA_Image<IA_IntPoint,S>	rval =
d780 4
a783 4
IA_Image<IA_IntPoint,S> neighborhood_reduction
(const IA_Neighborhood<IA_IntPoint,IA_IntPoint> &nbh,
 const IA_CoreImage<IA_IntPoint, T> &img,
 const IA_IntPointSet &dest_ps,
d787 1
a787 1
    if (nbh.type() == IA_InvariantNbh<IA_IntPoint,IA_IntPoint>::s_type()) {
d790 1
a790 1
	     ((IA_InvariantNbh<IA_IntPoint,IA_IntPoint>*) IA_FBI<IA_IntPoint,IA_IntPoint, T, S, T>::extract_baseptr(nbh))->value,
@


1.3
log
@Finish up the list of generic reductions.
@
text
@d11 3
d46 2
d158 1
a158 1
    zero_extend(img, src_ps, src_data, gamma_zero);
d280 1
a280 1
    zero_extend(img, src_ps, src_data, gamma_zero);
d408 1
a408 1
    zero_extend(img, src_ps, src_data, gamma_zero);
d532 1
a532 1
    zero_extend(img, src_ps, src_data, gamma_zero);
d658 1
a658 1
    zero_extend(img, src_ps, src_data, gamma_zero);
d765 1
a765 1
    zero_extend(img, src_ps, src_data, gamma_zero);
@


1.2
log
@generic neighborhood reductions are now available.
@
text
@d11 3
d286 1
a286 1
IA_Image<IA_IntPoint,S> neighborhood_Reduction
d290 1
a291 1
 T gamma_zero,
d327 128
d538 1
a538 1
IA_Image<IA_IntPoint,T> neighborhood_reductioN
d664 1
a664 1
IA_Image<IA_IntPoint,S> neighborhood_ReductioN
d668 1
a669 1
 T gamma_zero,
d677 107
@


1.1
log
@Initial revision
@
text
@d10 4
a13 1
// $Log: DDTempl.c,v $
d76 474
@
