/****************************************************************************
 *   gslab.h : 
 *   		header file for Morton Slabs.
 *
 *   Change Log :
 *		June 1997 Initial version,  Liujian Qian
 *
 *   $Id: gslab.h,v 1.2 1998/12/10 00:11:46 qian Exp $
 ***************************************************************************/

#ifndef _GGSlab_H_
#define _GGSlab_H_

#include "gcxx.h"
#include "gdatapipe.h"

#define SLAB_EXT	GFCConfig::grid_slab_size

class GGrid;


/**
  The morton slab used in conjunction with the Raster ADT.

  Morton Slab: a square of data cells. Its size is a power of 2;
  its starting coordinates (xlow/ylow) must be aligned on 
  multiplies of its size. All the coordinates are positive.

  Note: A) the data cells for a Morton slab is always contiguous 
	  in the Morton order. 
	B) Each slab has its unique order number inside the raster.
	   This  number is also in Morton order, naturaly. This order
	   number is used to index into the slabs index hold in the 
	   raster header.
        C) It is not to be visible by end users; it is solely
	  used by the GRaster class which is a real ADT.
        D) if the field compact_len is greater than 0, then this slab
	  has been compressed and this value indicates the size of the
	  compressed data (not including the header).
*/
class GSlab
{
public:    
    GCellType ctype;	//cell value type
    int  xlo, ylo;	//starting point of the square relative to the whole raster
    int  xhi, yhi;	//upper bound where data actually exist. 
    int  morder;	//morton order of this slab wrt the whole raster
    int  compact_len;   //lenght of the data after compression (not including hdr)

    char* data;		//1D array  for cell values of the slab; always 8-aligned

    int	  dirty;	//has this slab been modified?
    GGrid *grid;	//the grid this slab came from
    
public:

    /// 
    // ctor/dtor
    NOP			GSlab(GCellType t=CELL_INT16);
    NOP			GSlab(int xlow, int ylow, int xhi, int yhi, GCellType t=CELL_INT16);
    NOP			GSlab(const GSlab& g);
    virtual 		GSlab& operator= (const GSlab& g);
    virtual 		~GSlab ();

    virtual uint32  	getPSize() const;
    virtual Result 	init(void);

    /**
     * compares the morton order of two slabs.
     */
    virtual int    	cmp (const GSlab&) const ;

    virtual Result 	unpack	  (DataPipe& p) ;
    virtual Result 	pack	  (DataPipe& p);
    virtual Result 	store	  (DataPipe& p, DataPipe& zip_p);
    
    virtual void 	mbr	  (int&, int&, int&, int&) ;

    inline 
    int  		dataSize() const {return SLAB_EXT*SLAB_EXT*cvs(); }
    
    GCellType		cellType() const {return ctype;}

    void		setRange(int xlow, int ylow, int xhigh, int yhigh);
    
    ///
    // return the actual width of the slab
    int			width() const   { return xhi-xlo+1; }
    ///
    // return the actual height of the slab
    int			height() const  { return yhi-ylo+1; }
    ///
    // return the size of compressioned data
    inline int  	compactSize() const {return compact_len;} 
    ///
    // return the unique order number for this slab
    int			order() const {return morder; }

    bool 		isFull() const    {return 
					   (xhi-xlo+1==SLAB_EXT && yhi-ylo+1==SLAB_EXT); }
    ///
    // test if the slab is properly aligned.
    // an aligned Morton Slab has the starting x/y coordinates  
    // being multiply of its extent, which must be a power of 2.
    // necessary to ensure contiguous morton address inside the slab
    bool 		isAligned() const;

    void		clear();    

    ///
    // given a buf of contiguous rows, store 'em in a morton slab with starting point
    // at y_start and x_start. y_size is the number of last row; 
    // x_size  is the extent of each row in x dimension.
    Result		import(const char* rows_buf, int x_start, int y_start, 
			       int x_size, int  y_size);

    ///
    // compress the slab's data into the given pipe 
    // which will be extended/recycled before actual compression
    Result		zip (DataPipe& p);
    ///
    // uncompress the data hold in a data pipe (cursor)  into slab 'data' 
    Result		unzip(DataPipe& p);
    
    friend ostream& operator<<(ostream& s, const GSlab& slab);

    ///
    // get the cell value at (x,y); (x,y) is global coordinate
    // inside a raster.
    GCellValue		getCell(int x, int y) const;
    ///
    // set pixel value at (x,y); (x,y) is global coordinate
    // inside a raster.
    void		setCell(GCellValue val, int x, int y);

    ///
    // return a scan line of data; the line buffer is supported
    // by user which should be of enough size. 
    // y is an ordinate wrt the global raster;
    Result		scanLine (int y, char* line_buf);

    inline 
    static int		slabHdrSize()   {return sizeof(int)*7;}

protected:
    char*		data_buf;
    //
    // return the cell-value-size for a cell (4 bytes for 24/32 bpp)
    inline int		cvs() const ;
    void		allocDataSpace(unsigned s);
    void		freeDataSpace();
    
};

#define MAX_SLAB_SZ	(GSlab::slabHdrSize() + SLAB_EXT*SLAB_EXT*2)

/**
 * @internal
 *
 * structure for slab descriptors; a piece of info kept in the
 * the header of a raster to keep track of individual slabs.
 */
struct GSlabDesc
{
    int		order;	//morton order of the slab in the raster
    char	id[8];	//record id for the slab in database; or
	                //offset into a file where the slab data 
	                //starts. an opaque user data structure.
    GSlabDesc():order(-1) {}
    GSlabDesc& operator= (const GSlabDesc& s) 
    {
	order = s.order;
	for(int i=0; i<8; i++) id[i] = s.id[i];
	return *this;
    }
};



#endif

Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999