/* @(#)slsgd.c	19.1 (ES0-DMD) 02/25/03 14:25:41 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT       (c)  1988  European Southern Observatory
.LANGUAGE        C
.IDENTIFICATION  slslgd
.AUTHOR          Preben Grosbol  (ESO-IPG)
.KEYWORDS        Object search, single line, gradient detection
.ENVIRONMENT     MIDAS
.COMMENTS        Routines used for Measuring Machine facility
.PURPOSE         Fast search of objects in a single scan line
                 using a Laplacian gradient detection.
.RETURN          no. of objects found, <0 error
.VERSION         1.0   1988-Oct-08 :   Creation,     PJG
------------------------------------------------------------------------*/
#include   <mmfsrch.h>          /* definitions of search structures etc.*/

int slsgd(buf,np,obj,mm,noi,lev)
int      *buf;                  /* pointer to scan line to be searched  */
int        np;                  /* no. of pixels in scan line           */
OBJ      *obj;                  /* pointer to structure with objects    */
int        mm;                  /* size of moving mean filter           */
int       noi;                  /* noise level of data                  */
int       lev;                  /* detection level                      */
{
  int    *buff;
  int    nobj,nobg,bg,isg,n,ka,kf;
  int    kaf,kmg,nss,nsd,nzf,kzn,kax,i;
  int    n0,n1,n2,n3;
  float  gkm,axk,pm;
  float  ak,an,den,xs,xxs;

  nobj = 0; i = 2; nobg = 0;       /* initiate search parameters        */
  isg = 1; n = 0; nss = 0;
  kmg = 0; nzf = 0; kax = 0;
  den = 0.0; xs = 0.0; xxs = 0.0;

  if (mm<1) mm = 1; else if (np<=mm) return -1;
  lev *= mm; kzn = KZN * mm; pm = mm;

  n1 = 0; buff = buf;              /* initiate moving mean filter      */
  while (mm--) { n1 += *buf++; np--; }
  n2 = n1 + (*buf++) - (*buff++);
  n3 = n2 + (*buf++) - (*buff++);

  bg = n1;                             /* first pixel is background    */
  while (np--) {                       /* start search pixel by pixel  */
    i++;
    n0 = n1; n1 = n2; n2 = n3;
    n3 += (*buf++) - (*buff++);        /* compute new moving mean      */
    nsd = n0 - n1 - n2 + n3;           /* Laplacian gradient           */
 
    if (nobg || (nsd>lev && n0<n1)) {  /* pixel in object              */
       nobg = bg+noi<n3 || MPIX<n;
       if (nobg) {                     /* new object found             */
          n++;
          ka = n2 - bg;
          kf = n3 - n0;
          if (isg*kf < kzn) {          /* sign changes in gradient     */
             nss++;
             isg = (kf<0) ? -1 : 1;
          }
          ak = ka; an = n;
          den += ak;
	  ak  *= an;
          xs  += ak;
          xxs += ak*an;
          if (ka>kax) {                /* max. density, size of object */
            nzf += 4;
            if (ka-kax>20) nzf++;
            kax = ka;
          }
          kaf = (kf<0) ? -kf : kf;     /* max. absolute gradient       */
	  if (kaf>kmg) kmg = kaf;
          if (np && n<nzf) continue;
       }
       if (n>MPIX && nss>1) {         /* object has terminated         */
          gkm = kmg; axk = kax;
          obj->x = xs/den;
          obj->y = den/pm;
          obj->xs = xxs/pm;
          obj->ys = den/pm;
          obj->xy = xs/pm;
          obj->den = den/pm;
          obj->max = axk/pm;
          obj->bg  = bg/pm;
          obj->grad = 0.5*gkm/pm;
          obj->ix = i - n;
          obj->iy = 0;
	  obj->npix = n;
          obj->nline = 1;
	  obj++; nobj++;
       }
       nobg = 0;                       /* reset counters for new obj.  */
       isg = 1; n = 0; nss = 0;
       kmg = 0; nzf = 0; kax = 0;
       den = 0.0; xs = 0.0; xxs = 0.0;
    }
    bg = n0;
  }
  return nobj;
}
