/****************************************************************************
 *   gshapefile.h : 
 *   
 *		header file for  shape file reading utilities.
 *
 *   Change Log :
 *		 May 1997 Initial version,  Liujian Qian
 *
 *   $Id: gshapefile.h,v 1.13 1999/02/14 03:14:26 qian Exp $
 ***************************************************************************/
 
#ifndef _SHAPEFILE_H_
#define _SHAPEFILE_H_

#include "gadt.h"	//for getShapeRec(nth, GADT* val);
#include "gdatapipe.h"
#include "gmmap.h"
#include "gadt_arc.h"
#include "gadt_polygon.h"

#define AV_FILE_CODE	9994	
#define AV_HEADER_SIZE	100	//for both .shp and .shx files

//this macors returns the offset of nth record into the .shx files
#define AV_IDX_OFFSET(n)    (AV_HEADER_SIZE+(n)*sizeof(IndexRecord))

/**
 * @internal
 * common part of the struct for all ArcView shpaefile records
 */
struct GShpCommon
{
    int			type;
    unsigned char	Xmin[8];
    unsigned char	Ymin[8];
    unsigned char	Xmax[8];
    unsigned char	Ymax[8];
};

/**
 * @internal
 * ArcView format for a Point record
 */
struct GShpPoint //all in little endian
{
    int 		type;
    unsigned char	x[8];
    unsigned char	y[8];
};

/**
 * ArcView strucuture for Multipoints record

struct shp_MultiPoint
{
    //all in Little endian
    int 		type;
    unsigned char	Xmin[8];
    unsigned char	Ymin[8];	
    unsigned char	Xmax[8];
    unsigned char	Ymax[8];
    int			n_points;
    double*		points;
};
*/

/*
 * 
 * ArcView struct for Arc/Polygon shape record

struct shp_ArcPolygon
{
    //all in Little endian
    int 		type;
    unsigned char	Xmin[8];    
    unsigned char	Ymin[8];
    unsigned char	Xmax[8];
    unsigned char	Ymax[8];
    int			n_parts;
    int			n_points;
    int			*parts;	//index into points for each polyline
    double		*points;
};
*/


/**
 *
 *	@short ArcView shapefile reader class. 
 *
 *
 *        If you want to read associated 	attributes for each shape record, 
 *	use the class DBFile that comes with this class for that purpose.  
 *	This class only reads the geometry record in the .shp file which
 *
 *	is indexed by the .shx file. DBFile will read the .dbf file or
 *	tabular attributes. The tabular records and the geometry records
 *	have one-to-one mappings, and appear in the same order in the 
 *	.shp file and .dbf file respectively.
 */
class GShapeFile 
{
public:
    ///
    //current supported types of shapes in .shp file
    enum ShapeType {
	av_Null		= 0,
	av_Point	= 1,
	av_Arc		= 3,
	av_Polygon 	= 5,
	av_MultiPoint 	= 8
    };
    
    //structure for main file header record
    struct  MainFileHdr 
    {
	int		file_code;	//all in Big (Sun/Mortorola) endian
	int		unused1 [5];
	int		file_length;	//in 16-bit words

	int		version;	//all in Little (Intel) endian
	int		shape_type;
	unsigned char	Xmin[8];	//declare them as 'doubles' 
	unsigned char	Ymin[8];	//will cause wrong sizeof due to 
	unsigned char	Xmax[8];	//8-align for doubles on sparc.
	unsigned char	Ymax[8];	
	int		unused2[8];
    };

    //structure for main file record header
    struct RecordHdr		//Big endian.
    {
	int		record_no;	
	int		content_len;	//does NOT include this hdr!
    };

    typedef struct MainFileHdr IndexFileHdr;

    //structure for index file records
    struct IndexRecord 		//all in big endian
    {
	int	offset;		
	int	content_len;	//same as RecordHdr::conten_len
    };

private:	
    //attributes 
    MainFileHdr		main_hdr;
    IndexFileHdr	idx_hdr;
    int			n_records;
    int			type;
    char		name_prefix[256];
    GMMap*		main_mmap;      //memory-mapped files
    GMMap*		idx_mmap;
    GMMap*		dbf_mmap;

    DataPipe		rec_buf;	//for individual records
    DataPipe 		dpipe;		//for conversion to ADTs
    int			parts_a[GOps::max_parts]; 

    GSpatial		*srec;		//spatial record

    //private operations
    void		init();

public:		//interface for Shape File handling
    
    /**
     */
    GShapeFile ();
    /**
     * this constructor automatically opens the named shapefile
     * for read access.
     */
    GShapeFile (const char* name);
    /**
     */
    ~GShapeFile();
    /**
     * print the basic info. about the shapefile to the console.
     */
    friend ostream&	operator<<(ostream& os, const GShapeFile& shp);
    /**
     * GShapeFile :: openShapeFile --
     *
     *	Given a shape file name, tries to open the corresponding .shp,
     *	.shx, and .dbf files. If success then read the header info into
     *	in-memory structure. The files will be memory-mapped.
     *
     *	Return 0 upon success, otherwise -1. 
     *	
     * Side effects:
     * 	The three files are opened and header structures read into memory.
     *	Ready to retrieve individual shape/attribute records.
     */
    int    		openShapeFile (const char* name);

    /**
     * return the type of shape record in a shapefile. It is one 
     * of the following types:
     * av_Point, av_Arc, av_Polygon, av_MultiPoint, and av_Null if unknown.
     */
    ShapeType		shapeType  () const {return (ShapeType)type;}
    /**
     * return the number of records in a shapefile
     */
    int    		numRecords () const {return n_records;}
    /**
     * return the universal bounding rectangle for all the shape records 
     * in a shapefile. 
     */
    int    		bndRect    (double& xmin, double& ymin, 
				    double& xmax, double& ymax) const;    
    /**
     *	retrieve a shape record's information.
     *	
     *
     *	Return NULL if failed. Otherwise the following values 
     *	are set properly:
     *	verticies: contains all the verticies
     *	parts:     contains the parts index (in the unit of vertices) 
     *             into the "vertices" array. 
     *	           Each verticy has two double coordinates.
     *	n_parts:   number of parts
     *	n_verts:   number of total vertices (summed over all parts)
     *	vertices:  the array of vertices (pair of doubles).
     * 
     */
    Result  		getShapeRec (int nth, int& n_parts,
				     int& n_verts, int*& parts,
				     double*& vertices, GRect&);
    /**
     * return the pointer to the nth spatial record as a GFC ADT object.
     * the returned pointer points to a memory address owned by this 
     * GShapeFile object.  
     */
    GSpatial*		getShapeRec (int nth);
    /**
     * retrieves a shape record as a spatial GFC ADT.
     * val must be a valid pointer to the proper type of GFC ADTs.
     * The following is the correspondence between ArcView spatial types
     * and GFC spatail ADTs:
     * ArcView		GFC
     * point		GPoint
     * arc		GArc
     * polygon		GPolygon
     * multi-point	not-supported yet
     */
    Result		getShapeRec (int nth, GPoint* p);
    Result		getShapeRec (int nth, GArc* a);
    Result		getShapeRec (int nth, GPolygon* pg);

    /**
     * retrieve the mbr of 'nth' shape record
     */
    Result		getMBR(int nth, GRect& rect);

protected:

    // read the 'nth' record from the shapefile; return the
    // pointer to a copy of the record (internal-use only);
    // note that the generic record header (hdr_no + content_len)
    // is not included in the returned pointer.
    //
    char*  		recordCopy   (int nth);
    //
    // flip doubles
    void		flipCommon  (char* rec);
    //
    //
    void		flipHeaders ();
    //
    //
    void		copyMBR(double& xl, double& yl, 
				double& xh, double& yh, 
				char* rec);
    //
    //
    void  		allocSpatialRecord();
    /**
     * make full path to the shape file
     */
    char*		makePath(const char* name, char* dest=0);
    /**
     * get the offset (in bytes) of the nth record in the main (.shp) file.
     * The offset is relative to the beginning of the file and starts
     * with 0. 
     * @param  nth	is the number of record of concern. starts w/ 0.
     * @param  len      is the content length (in byte) of the record. 
     */ 
    long		mainRecordOffset(int nth, int& len);

    /**
     * gives advice about how the shapefile will be accessed
     */
    int			advise(int ad) ;
};

#endif







 

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