www.gusucode.com > VC++开源的SHP格式GIS地图查看软件源程序源码程序 > VC++开源的SHP格式GIS地图查看软件源程序源码程序\code\shpFile.cpp

    //Download by http://www.NewXing.com
#include "stdafx.h"
#include <d3dtypes.h>
#include "shpFile.h"
#include "MapPoint.h"
#include "MapPoints.h"
#include "MapLine.h"
#include "MapPolygon.h"
#include "MapFields.h"


CShpFile::CShpFile() 
{
	int i;
	bShpOpen = FALSE;
	bShxOpen = FALSE;
	m_shpType = NULLSHP;

	/* -------------------------------------------------------------------- */
            /*	Establish the byte order on this machine.			*/
    /* -------------------------------------------------------------------- */
    i = 1;
    if( *((uchar *) &i) == 1 )
		m_bBigEndian = FALSE;
	else
		m_bBigEndian = TRUE;
}

CShpFile::~CShpFile()
{
	
	 CMapPoint*    pPt;
	 CMapPoints*   pPts;
	 CMapLine*     pLine;
	 CMapPolygon*  pPolygon;

	 while(!m_ObList.IsEmpty())
	 {
		switch ( m_shpType )
        {  
			case POINT:
				pPt =(CMapPoint*)m_ObList.RemoveTail();
				delete pPt;
				break;
            case MULTIPOINT:
				pPts =(CMapPoints*)m_ObList.RemoveTail();
				delete pPts;
				break;

			case POLYLINE:
                pLine =(CMapLine*)m_ObList.RemoveTail();
				delete pLine;
				break;
			case POLYGON:
                pPolygon =(CMapPolygon*)m_ObList.RemoveTail();
				delete pPolygon;
				break;
            default:
				m_ObList.RemoveTail();
				break;
 
		}
     }    
	 if ( bShpOpen )
		fShp.Close();
	 if (bShxOpen)
		fShx.Close();
	 if ( pRecordSet )
		 delete pRecordSet;
	 
}

/*************************************************
  描述:         读入Shp、shx文件 格式 参阅ESRI技术白皮书
  输入:         文件名(全路径) 
  输出:        成功返回TRUE 失败返回FALSE
*************************************************/


BOOL CShpFile::ReadShp(CString& csFileName)
{
	int	  iTemp;
	CString csShxName;
	CFileException fe;
    SHPHEADER varHeader;
	
	//打开主文件
	if ( !fShp.Open(csFileName, CFile::modeRead|CFile::shareDenyWrite,&fe))
		return FALSE;
	bShpOpen = TRUE;
    
	//打开索引文件
	csShxName = csFileName.Left(csFileName.GetLength() - 3);
	
	csShxName = csShxName + "shx";
    if ( !fShx.Open(csShxName, CFile::modeRead|CFile::shareDenyWrite,&fe))
		return FALSE;
	bShxOpen = TRUE;
       

	TRY
    {
	    //读主文件头 长100字节
		if ( fShp.Read(&varHeader , sizeof(SHPHEADER))!= sizeof(SHPHEADER))
			return FILE_READERR;
		
        iTemp = varHeader.iFileCode; 
		if ( !m_bBigEndian )
			SwapWord(sizeof(int),&iTemp);
		if ( iTemp != 9994 ) //是否是shp文件
			return FILE_CODEERR;
        if ( varHeader.iVersion != FILE_VERSION ) //文件版本是否正确
			return FILE_VERSIONERR;
        
		//shp 类型  		
		m_shpType = varHeader.iShpType;  
		m_shpFileLength = varHeader.iFileLength;
	    if ( !m_bBigEndian )
			SwapWord(sizeof(int),&m_shpFileLength);
		
		//保存数据最大矩形范围
		m_Extent.SetLeft(varHeader.dbXMin);
		m_Extent.SetRight(varHeader.dbXMax);
		m_Extent.SetTop(varHeader.dbYMin);
		m_Extent.SetBottom(varHeader.dbYMax);
        
		//读索引文件头 长100字节
		if ( fShx.Read(&varHeader , sizeof(SHPHEADER))!= sizeof(SHPHEADER))
			return FILE_READERR;
		iTemp = varHeader.iFileCode; 
		if ( !m_bBigEndian )
			SwapWord(sizeof(int),&iTemp);
		if ( iTemp != 9994 ) //是否是shx文件
			return FILE_CODEERR;
        if ( varHeader.iVersion != FILE_VERSION ) //文件版本是否正确
			return FILE_VERSIONERR;
		m_shxFileLength = varHeader.iFileLength; 
		if ( !m_bBigEndian )
			SwapWord(sizeof(int),&m_shxFileLength);
		//通过索引文件计算主文件记录个数 文件长度数值以16位计
		m_iRecordCount = ((m_shxFileLength - 50 )*2)/sizeof(SHXRECORD);
		
		if ( !ReadRecord() )
			return FILE_READERR;
         if ( !ReadDBF(csFileName))
			 return FALSE;
	}
	CATCH(CFileException ,eload)
    {
		fShp.Abort();
		return FALSE;
    }
	END_CATCH
	
	
	return TRUE;

}
/*************************************************
  描述:         读入DBF文件格式 
  输入:         文件名(全路径) 
  输出:        成功返回TRUE 失败返回FALSE
*************************************************/
BOOL CShpFile::ReadDBF(CString& csFileName)
{
	CString csDbfName;
	BOOL bResult;
	//创建记录集对象
	pRecordSet = new CMapRecordSet;
	ASSERT ( pRecordSet != NULL ); 
	csDbfName = csFileName.Left(csFileName.GetLength() - 3);
	csDbfName = csDbfName + "dbf";
	//打开DBF文件
	bResult =  pRecordSet->openDBF(csDbfName); 
    if ( !bResult )
		delete pRecordSet;
	return bResult;
}

/*************************************************
  描述:         获得当前地图文件最大矩形范围 
  输入:         无
  输出:        地图矩形范围   
*************************************************/

CMapRectangle CShpFile::GetExtent()
{
	return m_Extent;
}

/*************************************************
  描述:         设置地图文件最大矩形范围 
  输入:         地图矩形范围
  输出:        无   
*************************************************/
void CShpFile::SetExtent(CMapRectangle& extent )
{
	m_Extent.SetLeft(extent.GetLeft());  
    m_Extent.SetRight(extent.GetRight());
	m_Extent.SetTop(extent.GetTop()); 
    m_Extent.SetBottom(extent.GetBottom());
}

/*************************************************
  描述:         设置Shp对象类型 
  输入:         shp 类型
  输出:        无   
*************************************************/
void CShpFile::SetShpType(int& iShpType)
{
	m_shpType = iShpType;
}

/*************************************************
  描述:         读入Shp对象坐标 
  输入:         无
  输出:        成功返回TRUE 失败返回FALSE  
*************************************************/

BOOL CShpFile::ReadRecord()
{
	int i,j,k,m;
	int iDataLen,iLength,iIndex;
	int *pIParts;
	double dbTmp;
	char *pszBuffer,*lpVer;
	BOOL bEof;
	SHPINFO shpIn;
	SHPRECORDHEADER RecordHeader;
    CMapRectangle objRectangle;
    CMapPoint   *pPoint;
	CMapPoints  *pPoints;
	CMapParts   *pParts;
	CMapLine    *pLine;
	CMapPolygon *pPolygon;
	
	bEof = FALSE;
	switch ( m_shpType )
	{
		case NULLSHP:	
			return FALSE;
			break;
        case POINT:
			{
				
				SHPPTCONTENT point;
				//读入点记录
				for ( i = 1 ; i <= m_iRecordCount ; i++ ) 
				{	
					iLength = SetRecordPos(i);
					if ( iLength <= 0 )
						return FALSE;

					//获得记录头信息
					if (!GetRecordHeader(RecordHeader))
						return FALSE;
					//记录内容长度是否与shp实体大小一致,索引记录长度是否与记录内容长度一致				
					if ( RecordHeader.iContentLength*2 != sizeof(point)||
						RecordHeader.iContentLength*2 != iLength)
						return FALSE;
					if(fShp.Read(&point,sizeof(point))!= sizeof(point))
							return FALSE;
					pPoint = new CMapPoint;
					iIndex = i - 1;
				    pPoint->SetIndex(iIndex); 
					if ( pPoint == NULL )
						return FALSE;
					//类型是否匹配
					if ( point.iShpType != m_shpType) 
						return FALSE;
                    pPoint->SetX(point.dbX );
					pPoint->SetY(point.dbY );
					m_ObList.AddTail(pPoint);  
								    
				 } 
			} 	
			break;
        case POLYLINE:
		    
			pszBuffer = new char [MAX_BUFFER_SIZE]; //分配缓冲区
			if ( pszBuffer == NULL )
				return FALSE;
			memset(pszBuffer , 0 , MAX_BUFFER_SIZE);
            
			//读入线记录
			for ( i = 1 ; i <= m_iRecordCount ; i++ ) //m_iRecordCount
			{	
			
				iLength = SetRecordPos(i);
				if ( iLength <= 0 )
					return FALSE;

				pLine = new CMapLine();
				iIndex = i - 1;
				pLine->SetIndex(iIndex); 
				if ( pLine == NULL )
					return FALSE;
				//获得记录头信息
				if (!GetRecordHeader(RecordHeader))
					return FALSE;
				if ( !GetShpInfo(shpIn))
					return FALSE;
				 if (shpIn.ishpType != POLYLINE )//类型不匹配
                 {  
                      delete pLine;
					  continue;
				 }
				 if ( shpIn.iNumParts*sizeof(int) > MAX_BUFFER_SIZE )
                 {
					 //多义线段数大于最大缓冲区长度,忽略该对象
					 delete pLine;
					 continue;
                 } 
				 //计算对象内容实际长度
				 j = sizeof(SHPINFO) + shpIn.iNumParts*sizeof(int) ;
				 j += shpIn.iNumPoints*sizeof(SHPPOINT);  
                 
				 //判断实际长度是否与索引文件中记录的一致 
				 if ( RecordHeader.iContentLength*2 != j )
                 {
				     delete pLine;
					 continue;
				 }	 
				 //设置shp矩形范围
				 objRectangle.SetLeft(shpIn.Box[0].dbX);
				 objRectangle.SetTop(shpIn.Box[0].dbY);
				 objRectangle.SetRight(shpIn.Box[1].dbX);
				 objRectangle.SetBottom(shpIn.Box[1].dbY);
				 pLine->SetExtent(objRectangle);
				 pIParts = new int[shpIn.iNumParts];
				 if ( pIParts == NULL )
                 {
					delete pLine;
					return FALSE;
				 }
				 //读入多义线段索引
				 if ( fShp.Read(pIParts,shpIn.iNumParts*4) != (uint)(shpIn.iNumParts*4))
				 {
					delete pLine;
					return FALSE;
				 }

				 //点坐标存储所占字节数
				 iLength = shpIn.iNumPoints*sizeof(SHPPOINT);
				 //初始化缓冲区数据
				 iDataLen = ReadPoint(pszBuffer,iLength,bEof);
				 if ( iDataLen < 0 )
                 {
					  delete pLine;
					  delete pIParts;
					  return FALSE;
				 
				 }	 
				 lpVer = pszBuffer;
				 for ( j = 0 ;  j < shpIn.iNumParts ; j++ )
				 {
					pParts  = new CMapParts();
					pPoints = new CMapPoints();
 					if ( pParts == NULL || pPoints == NULL)
						return FALSE;
					if ( j == shpIn.iNumParts - 1 )
                    {
					    k = pIParts[j];        //本段第一个顶点索引
					    m = shpIn.iNumPoints ; //下一个段第一个顶点索引 
                    }
              	    else
                    {
						k = pIParts[j];
						m = pIParts[j+1];
					}
					//处理第i段的顶点
				    for ( ; k < m ; k++)
                    {   
						pPoint = new CMapPoint();
						if ( pPoint == NULL )
							return FALSE;
						
						//需要读入数据更新缓冲区
						if ( lpVer == pszBuffer + iDataLen && !bEof)
						{
							iDataLen = ReadPoint(pszBuffer,iLength,bEof);
							if ( iDataLen < 0 )
							{
								delete pPoint;
								delete pPoints;
								delete pLine;
								delete pIParts;
								
								return FALSE;
				 
							}	 
							lpVer = pszBuffer;
						}	
						dbTmp = *(double*)lpVer;
					    pPoint->SetX(dbTmp);
                        lpVer += 8;
						//需要读入数据更新缓冲区
						if ( lpVer == pszBuffer + iDataLen && !bEof)
						{
							iDataLen = ReadPoint(pszBuffer,iLength,bEof);
							if ( iDataLen < 0 )
							{
								delete pPoint;
								delete pPoints;
								delete pLine;
								delete pIParts;
								return FALSE;
				 
							}	 
							lpVer = pszBuffer;
						}	
						dbTmp = *(double*)(lpVer);
						lpVer += 8;
                        pPoint->SetY(dbTmp); 
						pPoints->Add(pPoint); 
						
					}  
                    pParts->Add(pPoints);   
				    pLine->Add(pParts); 

				 }
				 m_ObList.AddTail( pLine);
				 delete []pIParts;
			
            }
			delete []pszBuffer;

			break;
        case POLYGON:
			pszBuffer = new char [MAX_BUFFER_SIZE]; //分配缓冲区
			if ( pszBuffer == NULL )
				return FALSE;
			memset(pszBuffer , 0 , MAX_BUFFER_SIZE);
            
			//读入多边形记录
			for ( i = 1 ; i <= m_iRecordCount ; i++ ) //m_iRecordCount
			{	
				iLength = SetRecordPos(i);
				if ( iLength <= 0 )
					return FALSE;

				pPolygon = new CMapPolygon();
				iIndex = i - 1;
                pPolygon->SetIndex(iIndex);
				if (pPolygon == NULL )
					return FALSE;
				//获得记录头信息
				if (!GetRecordHeader(RecordHeader))
					return FALSE;
				if ( !GetShpInfo(shpIn))
					return FALSE;
				 if (shpIn.ishpType != POLYGON )//类型不匹配
                 {  
                      delete pPolygon;
					  continue;
				 }
				 if ( shpIn.iNumParts*sizeof(int) > MAX_BUFFER_SIZE )
                 {
					 //复合多边型中的多边形个数大于最大缓冲区长度,忽略该对象
					 delete pPolygon;
					 continue;
                 } 
				 //计算对象内容实际长度
				 j = sizeof(SHPINFO) + shpIn.iNumParts*sizeof(int) ;
				 j += shpIn.iNumPoints*sizeof(SHPPOINT);  
                 
				 //判断实际长度是否与索引文件中记录的一致 
				 if ( RecordHeader.iContentLength*2 != j )
                 {
				     delete pPolygon;
					 continue;
				 }	 
				 //设置shp矩形范围
				 objRectangle.SetLeft(shpIn.Box[0].dbX);
				 objRectangle.SetTop(shpIn.Box[0].dbY);
				 objRectangle.SetRight(shpIn.Box[1].dbX);
				 objRectangle.SetBottom(shpIn.Box[1].dbY); 
				 pPolygon->SetExtent(objRectangle);
				 pIParts = new int[shpIn.iNumParts];
				 if ( pIParts == NULL )
                 {
					delete pPolygon;
					return FALSE;
				 }
				 //读入复合多边型段索引
				 if ( fShp.Read(pIParts,shpIn.iNumParts*4) != (uint)(shpIn.iNumParts*4))
				 {
					delete pPolygon;
					return FALSE;
				 }

				 //点坐标存储所占字节数
				 iLength = shpIn.iNumPoints*sizeof(SHPPOINT);
				 //初始化缓冲区数据
				 iDataLen = ReadPoint(pszBuffer,iLength,bEof);
				 if ( iDataLen < 0 )
                 {
					  delete pPolygon;
					  delete pIParts;
					  return FALSE;
				 
				 }	 
				 lpVer = pszBuffer;
				 for ( j = 0 ;  j < shpIn.iNumParts ; j++ )
				 {
					pParts  = new CMapParts();
					pPoints = new CMapPoints();
 					if ( pParts == NULL || pPoints == NULL)
						return FALSE;
					if ( j == shpIn.iNumParts - 1 )
                    {
					    k = pIParts[j];        //本段第一个顶点索引
					    m = shpIn.iNumPoints ; //下一个段第一个顶点索引 
                    }
              	    else
                    {
						k = pIParts[j];
						m = pIParts[j+1];
					}
					//处理第i段的顶点
				    for ( ; k < m ; k++)
                    {   
						pPoint = new CMapPoint();
						if ( pPoint == NULL )
							return FALSE;
						
						//需要读入数据更新缓冲区
						if ( lpVer == pszBuffer + iDataLen && !bEof)
						{
							iDataLen = ReadPoint(pszBuffer,iLength,bEof);
							if ( iDataLen < 0 )
							{
								delete pPolygon;
								delete pIParts;
								return FALSE;
				 
							}	 
							lpVer = pszBuffer;
						}	
						dbTmp = *(double*)lpVer;
					    pPoint->SetX(dbTmp);
                        lpVer += 8;
						//需要读入数据更新缓冲区
						if ( lpVer == pszBuffer + iDataLen && !bEof)
						{
							iDataLen = ReadPoint(pszBuffer,iLength,bEof);
							if ( iDataLen < 0 )
							{
								delete pPolygon;
								delete pIParts;
								return FALSE;
				 
							}	 
							lpVer = pszBuffer;
						}	
						dbTmp = *(double*)(lpVer);
                        pPoint->SetY(dbTmp); 
						pPoints->Add(pPoint); 
						lpVer += 8;
						
					}  
                    pParts->Add(pPoints);   
				    pPolygon->Add(pParts); 

				 }
				 m_ObList.AddTail( pPolygon);
			     delete []pIParts;
            }
			delete []pszBuffer;
			break;
		default:
			return FALSE;
			break;

    }    
	return TRUE;   

}

/*************************************************
  描述:         计算每条shp对象相对文件头的偏移量
  输入:         记录索引值(从零开始)
  输出:        该shp对象数据在文件中的位置  
*************************************************/
int CShpFile::SetRecordPos( int iRecord )
{
    unsigned int iOffset,iTmp;
	SHXRECORD shxRD;

	if ( iRecord < 0 )
		return 0;
    //获得索引文件记录偏移量相对文件头
	if (iRecord == 1 )
    	iOffset = sizeof(SHPHEADER)  ;	 
	else
		iOffset = sizeof(SHPHEADER) + (iRecord-1)*sizeof(shxRecord) ;
	if ( iOffset > m_shxFileLength*2 - sizeof(shxRecord) )
		return 0;
	fShx.Seek( iOffset , CFile::begin );
	int m = sizeof(shxRD);
	fShx.Read( &shxRD , sizeof(shxRD));
	iTmp = shxRD.iOffset;
	SwapWord(sizeof(int),&iTmp);
	fShp.Seek(iTmp*2 ,  CFile::begin );
	iTmp = shxRD.iContentLength;
	SwapWord(sizeof(int),&iTmp);
   
	
	return iTmp*2;	
}

/*************************************************
  描述:         获得每条shp对象记录记录头的信息
  输入:         记录头结构对象
  输出:        成功返回TRUE 失败返回FALSE    
*************************************************/

BOOL CShpFile::GetRecordHeader(SHPRECORDHEADER& RecordHeader )
{
	int iLength,iNum;

	if(fShp.Read(&RecordHeader,sizeof(RecordHeader))!= sizeof(RecordHeader))
		return FALSE;
	if ( !m_bBigEndian )
    {  
		iNum    = RecordHeader.iRecordNum;
        iLength = RecordHeader.iContentLength;
		SwapWord(sizeof(int),&iLength);
		SwapWord(sizeof(int),&iNum);
		RecordHeader.iRecordNum = iNum;
        RecordHeader.iContentLength = iLength;
	}
    return TRUE;


}
/*************************************************
  描述:         获得每条shp对象描述信息
  输入:         描述信息结构对象
  输出:        成功返回TRUE 失败返回FALSE    
*************************************************/

BOOL CShpFile::GetShpInfo(SHPINFO& varInfo)
{

	if(fShp.Read(&varInfo,sizeof(varInfo))!= sizeof(varInfo))
		return FALSE;
	return TRUE;
}

/*************************************************
  描述:         读入点对象数据
  输入:         数据缓冲区指针 缓冲区最大32K 
                如果超出需要分多次读取,要读取的长度、
				是否已读取完成
  输出:        读取数据的实际长度   
*************************************************/

int  CShpFile::ReadPoint(char* pszBuffer,int& iLength,BOOL& bEof)
{
	if ( iLength > MAX_BUFFER_SIZE)
    {
		iLength -= MAX_BUFFER_SIZE;
		if ( fShp.Read(pszBuffer,MAX_BUFFER_SIZE) != MAX_BUFFER_SIZE )
			return FILE_READERR;
		bEof = FALSE;
		return MAX_BUFFER_SIZE;
    }
    else
    {   
		if ( fShp.Read(pszBuffer,iLength) != (uint)iLength )
			return FILE_READERR;
		bEof = TRUE;
		return iLength;
	}     
}


/*************************************************
  描述:         根据点对象查找shp对象是否选中
  输入:         点对象
  输出:        查找到shp对象的索引值 返回值-表示未查找到   
*************************************************/
int CShpFile::SearchShape(CMapPoint& pt )
{
	unsigned long iCount;
	POSITION pos;
    CMapPolygon *pPolygon;

	if ( GetShpType() != POLYGON ) //只判断多边形对象
		return -1;
	iCount = m_ObList.GetCount()-1;
	
	for ( pos = m_ObList.GetHeadPosition()  ; pos != NULL ;  )
    {
		pPolygon = (CMapPolygon*)m_ObList.GetAt(pos);
		if ( pPolygon->IsPointIn(pt) )
		 	return pPolygon->GetIndex(); 
		m_ObList.GetNext(pos); 
    } 
	return -1;

}

/*************************************************
  描述:         绘制shp对象
  输入:         设备指针、图例对象指针、坐标变换参数结构对象
  输出:        无
*************************************************/
void CShpFile::DrawShp(CDC*pDC ,  CMapRender* m_pRender , DrawParam& draw )
 {           
    
	 int iDrawMode;

	 //计算当前屏幕的实际坐标范围
	 m_CurMapExtent.SetLeft(draw.m_StartX );
	 m_CurMapExtent.SetBottom(draw.m_StartY);
	 m_CurMapExtent.SetRight(draw.m_StartX + draw.m_ScreenWidth * draw.m_Scale);
	 m_CurMapExtent.SetTop(draw.m_StartY - draw.m_ScreenHeigh *draw.m_Scale);  
	 
	 //设置绘制模式
	 iDrawMode = pDC->SetROP2(R2_COPYPEN);
	 
	 switch ( m_shpType )
     {
		 case POINT: 
			{
                DrawPoint(pDC , m_pRender ,  draw );
			}	
			break;
         case POLYLINE: 
			{
			    DrawPLine(pDC , m_pRender ,  draw );
				
			} 
            break;
		 case POLYGON: 
			{
			    DrawPolygon(pDC , m_pRender ,  draw );

			}  
		    break;   	 
        default:
			break;
	 }
	 pDC->SetROP2(iDrawMode);
	 //int r = RGB_GETRED(16773020);
	 //int g = RGB_GETGREEN(16773020);
	 //int b = RGB_GETBLUE(16773020);

    
 
 }

/*************************************************
  描述:         对选中的shp对象闪烁
  输入:         设备指针、坐标变换参数结构对象、
                shp对象的索引值
  输出:        无
*************************************************/

void  CShpFile::FlashShp(CDC*pDC , DrawParam& draw , int iIndex)
{
	
	 int i,j,k,m,iCount,iDrawMode;
	 CMapPoint *pPoint;
	 CMapPoints *pPoints;
	 CMapParts *pParts;
	 //CMapLine  *pPline;
	 CMapPolygon *pPolygon;
	 CMapRectangle MapExtent;
	 CPoint    *pPtArray;  //顶点数组
	 int       *pPolygonCount; //每个多边型的顶点数组
	 CRect  rc;
	 POSITION pos;
	 CBrush br1(RGB(0,0,0));
     CBrush br2(RGB(255,255,255));
	 CBrush *pOldBrush;
	
	  if ( iIndex < 0 )
		  return;
	 iDrawMode = pDC->SetROP2(R2_XORPEN);
	 switch ( m_shpType )
	 {
		case POINT: {
					}
		break;	
		case POLYLINE: {
					   }
        break; 
		case POLYGON: {
			for ( pos = m_ObList.GetHeadPosition()  ; pos != NULL ;  )
			{
				pPolygon = (CMapPolygon*)m_ObList.GetAt(pos);
		        if (iIndex == pPolygon->GetIndex() )
				{
						iCount = pPolygon->GetCount(); //多边形个数
                    pPolygonCount = new int[iCount];
					if ( pPolygonCount == NULL )
						return;
					
					//计算复合多边型每部分的顶点数,和总顶点数
					
					for ( m= 0,i = 0 ; i < pPolygon->GetCount() ; i++ )
					{
						pParts =  pPolygon->GetParts(i);
						k = 0;
						for ( j = 0 ; j < pParts->GetCount() ; j++)
						{
							pPoints = pParts->Get(j); 
                            k += pPoints->GetCount();
						} 
						pPolygonCount[i] = k;
						m += k;
					}
					pPtArray = new CPoint[m];
                    if ( pPtArray == NULL )
                    { 
						delete []pPolygonCount;
						return ;
					}
					
					for ( m= 0 , i = 0 ; i < pPolygon->GetCount() ; i++ )
					{
						pParts =  pPolygon->GetParts(i);
						for ( j = 0 ; j < pParts->GetCount() ; j++)
						{
							pPoints = pParts->Get(j); 
                            for ( k = 0 ; k < pPoints->GetCount(); k++ )
                            {
								pPoint = pPoints->Get(k); 
								pPtArray[m].x = (int)((pPoint->GetX() - draw.m_StartX)/draw.m_Scale);
                                pPtArray[m++].y =  (long)((draw.m_StartY - pPoint->GetY() )/draw.m_Scale);
								
							}	
						} 
						
					}
					pOldBrush = pDC->SelectObject(&br1); 
					if ( pPolygon->GetCount() > 1)
                    { 
						
						pDC->PolyPolygon(pPtArray,pPolygonCount,iCount);
                        i = 0;
						while ( i < 150000 )
                        {
							i++;
						}	
						pDC->PolyPolygon(pPtArray,pPolygonCount,iCount);
						pDC->SelectObject(&br2);
						pDC->PolyPolygon(pPtArray,pPolygonCount,iCount);
						i = 0;
						while ( i < 350000 ) //延时
                        {
							i++;
						}
						pDC->PolyPolygon(pPtArray,pPolygonCount,iCount);
					
					}	
					else
                    {      
					   pDC->Polygon(pPtArray, m);
					   i = 0;
					   while ( i < 150000 )
                       {
							i++;
					   }
					   pDC->Polygon(pPtArray, m);
					   pDC->SelectObject(&br2);
					   pDC->Polygon(pPtArray, m);
					   i = 0;
					   while ( i < 350000 )
                       {
							i++;
					   }
					   pDC->Polygon(pPtArray, m);

					}	
					delete []pPolygonCount;
					delete []pPtArray;
                    pDC->SelectObject(pOldBrush); 
					break;   
                }
				m_ObList.GetNext(pos); 
			} 

		
		}
		break;
        default:
		break;	

	 } 
	 pDC->SetROP2(iDrawMode); 

}

/*************************************************
  描述:         绘制点对象
  输入:         设备指针、图例对象指针、坐标变换参数结构对象
  输出:        无
*************************************************/
void CShpFile::DrawPoint(CDC*pDC ,  CMapRender* m_pRender , DrawParam& draw )
{
	
	int    iIndex,iField;
	CBrush *pOldBrush;
	SIMPLERENDER simpleRender;
	CBrush brSimple;
	CPen   pen;
	CBrush br(RGB(255,239,156));
	CMapFields *pFields;
    CMapField  *pField;
    CMapPoint *pPoint;
	POSITION pos;
	CString csValue;
	RENDERINFO *rInfo;
	
	if ( m_pRender == NULL )
    {
		pOldBrush = pDC->SelectObject(&br);
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pPoint = (CMapPoint*)m_ObList.GetAt(pos);
			//判断要绘制的的对象是否在当前屏幕范围内
			if ( !m_CurMapExtent.IsPointIn(*pPoint)) 
            {
			
				m_ObList.GetNext(pos);
				continue;
            }
			DrawPointElement(pDC,pPoint,draw );
			m_ObList.GetNext(pos);

		}
		pDC->SelectObject(pOldBrush);
		
	} else if (	m_pRender->GetRenderType() == SIMPLE_RENDER )
	{
		m_pRender->GetSimpleRender(simpleRender);
		//pen.CreatePen(PS_SOLID,1,simpleRender.OutlineColor);
		if ( simpleRender.iIndex == 0 )
        {  
        	brSimple.CreateSolidBrush(simpleRender.FillColor);
			pOldBrush = pDC->SelectObject(&brSimple);
        }
        else
		{	
		   if (!brSimple.CreateHatchBrush( simpleRender.iIndex,
			                               simpleRender.FillColor))
		   { 
			  pOldBrush = pDC->SelectObject(&br);
		   } 
		   else
           {
			  pOldBrush = pDC->SelectObject(&brSimple);	
		   }   
		} 
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pPoint = (CMapPoint*)m_ObList.GetAt(pos);
			if ( !m_CurMapExtent.IsPointIn(*pPoint)) 
            {
				m_ObList.GetNext(pos);
				continue;
            }
			DrawPointElement(pDC,pPoint,draw );
			m_ObList.GetNext(pos);
		}
		pDC->SelectObject(pOldBrush);
		pen.DeleteObject();
		brSimple.DeleteObject(); 

        
    } 
	else if (	m_pRender->GetRenderType() == UNIQUE_RENDER )
    { 
		iField = m_pRender->GetFieldIndex();
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			
			pPoint = (CMapPoint*)m_ObList.GetAt(pos);
			if ( !m_CurMapExtent.IsPointIn(*pPoint)) 
            {
				m_ObList.GetNext(pos);
				continue;
            }
            iIndex = pPoint->GetIndex();
            pRecordSet->Move(iIndex,BookmarkFirst);
			pFields = pRecordSet->GetFields(0);
			if ( iField >= 0 && iField < pFields->GetCout())   
			{  
				pField = pFields->GetField(iField);
				csValue = pField->GetValueAsString();
				rInfo = m_pRender->GetByValue(csValue);
				ASSERT(rInfo);
				CBrush brush(rInfo->clr); 
			    pOldBrush = pDC->SelectObject(&brush);
			    DrawPointElement(pDC,pPoint,draw );
                pDC->SelectObject(pOldBrush);
			}
			m_ObList.GetNext(pos);

		}


	}
}

/*************************************************
  描述:         绘制单个的点对象
  输入:         设备指针、点对象对象指针、
                坐标变换参数结构对象
  输出:        无
*************************************************/

void CShpFile::DrawPointElement(CDC*pDC,CMapPoint *pPoint, DrawParam& draw )
{
	int iX,iY;
	CRect rc;

	if ( pPoint == NULL )
		return;
	
	iX = (int)((pPoint->GetX()-draw.m_StartX )/draw.m_Scale);
	iY = (int)((draw.m_StartY-pPoint->GetY())/draw.m_Scale);

	rc.left = iX - 4;
	rc.right = iX  + 4;
	rc.top = iY  - 4;
	rc.bottom = iY  + 4;
	pDC->Rectangle(&rc); 

}

/*************************************************
  描述:         绘制线对象
  输入:         设备指针、图例对象指针、坐标变换参数结构对象
  输出:        无
*************************************************/
void CShpFile::DrawPLine(CDC*pDC ,  CMapRender* m_pRender , DrawParam& draw )
{
    int    iIndex,iField; 
	CPen   *pOldPen;
	SIMPLERENDER simpleRender;
	CPen   penSimple;
	CPen   pen(PS_SOLID,1,RGB(255,0,0));
	CBrush br(RGB(255,239,156));
	CMapFields *pFields;
    CMapField  *pField;
   	CMapLine *pLine;
	POSITION pos;
	CString csValue;
	CMapRectangle shpRC;
	RENDERINFO *rInfo;
	if ( m_pRender == NULL )
    {
		pOldPen = pDC->SelectObject(&pen);
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pLine = (CMapLine*)m_ObList.GetAt(pos);
            shpRC = pLine->GetExtent();
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{	
				m_ObList.GetNext(pos);
				continue;
			}
			DrawPLineElement(pDC,pLine,draw );
			m_ObList.GetNext(pos);

		}
		pDC->SelectObject(pOldPen);
		
	} else if (	m_pRender->GetRenderType() == SIMPLE_RENDER )
	{
		m_pRender->GetSimpleRender(simpleRender);
		if ( simpleRender.iIndex == 0 )
        {  
        	pOldPen = pDC->SelectObject(&pen);
        }
        else
		{	
		   if (!penSimple.CreatePen(PS_SOLID,1,simpleRender.FillColor))
		   { 
			  pOldPen = pDC->SelectObject(&pen);
		   } 
		   else
           {
			   pOldPen = pDC->SelectObject(&penSimple);	
		   }   
		} 
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pLine = (CMapLine*)m_ObList.GetAt(pos);
			shpRC = pLine->GetExtent();
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{	
				m_ObList.GetNext(pos);
				continue;
			}
			DrawPLineElement(pDC,pLine,draw );
			m_ObList.GetNext(pos);
		}
		pDC->SelectObject(pOldPen);

		if ( penSimple.GetSafeHandle() != NULL ) 
	         penSimple.DeleteObject();  
		
        
    } 
	else if (m_pRender->GetRenderType() == UNIQUE_RENDER )
    { 
		iField = m_pRender->GetFieldIndex();
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			
			pLine = (CMapLine*)m_ObList.GetAt(pos); 
			shpRC = pLine->GetExtent();
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{	
				m_ObList.GetNext(pos);
				continue;
			}
            iIndex = pLine->GetIndex();
            pRecordSet->Move(iIndex,BookmarkFirst);
			pFields = pRecordSet->GetFields(0);
			if ( iField >= 0 && iField < pFields->GetCout())   
			{  
				pField = pFields->GetField(iField);
				csValue = pField->GetValueAsString();
				rInfo = m_pRender->GetByValue(csValue);
				ASSERT(rInfo);
				CPen penTemp(PS_SOLID,1,rInfo->clr); 
			    pOldPen = pDC->SelectObject(&penTemp);
			    DrawPLineElement(pDC,pLine,draw );
                pDC->SelectObject(pOldPen);
			}
			m_ObList.GetNext(pos);

		}


	}
			

}
/*************************************************
  描述:         绘制单个的线对象
  输入:         设备指针、线对象对象指针、
                坐标变换参数结构对象
  输出:        无
*************************************************/

void CShpFile::DrawPLineElement(CDC*pDC, CMapLine *pPline , DrawParam& draw )
{

	int i,j,k,iCount;
	CMapPoint *pPoint;
	CMapPoints *pPoints;
	CMapParts *pParts;
	CMapRectangle MapExtent;
	CPoint    *pPtArray;  //顶点数组

	if ( pPline == NULL )
		return;
	for ( i = 0 ; i < pPline->GetCount() ; i++ )
	{			
		pParts =  pPline->GetParts(i);
		for ( j = 0 ; j < pParts->GetCount() ; j++)
		{
			pPoints = pParts->Get(j); 
			iCount = pPoints->GetCount();
			pPtArray = new CPoint[iCount];
			if ( pPtArray == NULL )
				return ;
			for ( k = 0 ; k < iCount; k++)
			{	
				pPoint = pPoints->Get(k); 
				pPtArray[k].x = (int)((pPoint->GetX()-draw.m_StartX)/draw.m_Scale);
				pPtArray[k].y = (int)((draw.m_StartY - pPoint->GetY())/draw.m_Scale);
    
			}
		}	
	}
	//绘制多义线
	pDC->Polyline(pPtArray,pPoints->GetCount()); 
	delete []pPtArray;
				

}

/*************************************************
  描述:         绘制面对象
  输入:         设备指针、图例对象指针、坐标变换参数结构对象
  输出:        无
*************************************************/
void CShpFile::DrawPolygon(CDC*pDC ,  CMapRender* m_pRender , DrawParam& draw )
{
	int    iIndex,iField; 
	//CPen   *pOldPen;
	CBrush *pOldBrush;
	SIMPLERENDER simpleRender;
	CBrush brSimple;
	CPen   pen;
	CBrush br(RGB(255,239,156));
	CMapFields *pFields;
    CMapField  *pField;
   	POSITION pos;
	CString csValue;
	RENDERINFO *rInfo;
	CMapPolygon *pPolygon;
	CMapRectangle shpRC;

	if ( m_pRender == NULL )
    {
		pOldBrush = pDC->SelectObject(&br);
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pPolygon = (CMapPolygon*)m_ObList.GetAt(pos);
			shpRC = pPolygon->GetExtent(); 
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{
				//要绘制的对象外接矩形是不是与屏幕相交
				m_ObList.GetNext(pos);
				continue;
            }
			DrawPolygonElement(pDC,pPolygon,draw );
			m_ObList.GetNext(pos);

		}
		pDC->SelectObject(pOldBrush);
		
	} else if (	m_pRender->GetRenderType() == SIMPLE_RENDER )
	{
		m_pRender->GetSimpleRender(simpleRender);
		//pen.CreatePen(PS_SOLID,1,simpleRender.OutlineColor);
		if ( simpleRender.iIndex == 0 )
        {  
        	brSimple.CreateSolidBrush(simpleRender.FillColor);
			pOldBrush = pDC->SelectObject(&brSimple);
        }
        else
		{	
		   if (!brSimple.CreateHatchBrush( simpleRender.iIndex,
			                               simpleRender.FillColor))
		   { 
			  pOldBrush = pDC->SelectObject(&br);
		   } 
		   else
           {
			  pOldBrush = pDC->SelectObject(&brSimple);	
		   }   
		} 
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			pPolygon = (CMapPolygon*)m_ObList.GetAt(pos);
			shpRC = pPolygon->GetExtent();
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{
				//要绘制的对象外接矩形是不是与屏幕相交
				m_ObList.GetNext(pos);
				continue;
            }
			DrawPolygonElement(pDC,pPolygon,draw );
			m_ObList.GetNext(pos);
		}
		pDC->SelectObject(pOldBrush);
		if ( brSimple.GetSafeHandle() != NULL )
			brSimple.DeleteObject(); 

        
    } 
	else if (	m_pRender->GetRenderType() == UNIQUE_RENDER )
    { 
		iField = m_pRender->GetFieldIndex();
		for( pos = m_ObList.GetHeadPosition(); pos != NULL; )
		{  
			
			pPolygon = (CMapPolygon*)m_ObList.GetAt(pos);
            shpRC = pPolygon->GetExtent(); 
			if ( !m_CurMapExtent.IsInsercet(shpRC))
			{
				//要绘制的对象外接矩形是不是与屏幕相交
				m_ObList.GetNext(pos);
				continue;
            }
	        iIndex = pPolygon ->GetIndex();
            pRecordSet->Move(iIndex,BookmarkFirst);
			pFields = pRecordSet->GetFields(0);
			if ( iField >= 0 && iField < pFields->GetCout())   
			{  
				pField = pFields->GetField(iField);
				csValue = pField->GetValueAsString();
				rInfo = m_pRender->GetByValue(csValue);
				ASSERT(rInfo != NULL);
				CBrush brush(rInfo->clr); 
			    pOldBrush = pDC->SelectObject(&brush);
			    DrawPolygonElement(pDC,pPolygon,draw );
                pDC->SelectObject(pOldBrush);
			}
			m_ObList.GetNext(pos);

		}


	}
}

/*************************************************
  描述:         绘制单个的面对象
  输入:         设备指针、面对象对象指针、
                坐标变换参数结构对象
  输出:        无
*************************************************/

void CShpFile::DrawPolygonElement(CDC*pDC , CMapPolygon* pPolygon , DrawParam& draw )
{
	int i,j,k,m,iCount;
	CMapPoint *pPoint;
	CMapPoints *pPoints;
	CMapParts *pParts;
	CPoint    *pPtArray;  //顶点数组
	int       *pPolygonCount; //每个多边型的顶点数组

	if ( pPolygon == NULL )
		return;
	iCount = pPolygon->GetCount(); //多边形个数
    pPolygonCount = new int[iCount];
    
	if ( pPolygonCount == NULL )
		return;
					
	//计算复合多边型每部分的顶点数,和总顶点数
	for ( m= 0,i = 0 ; i < pPolygon->GetCount() ; i++ )
	{
		pParts =  pPolygon->GetParts(i);
		k = 0;
		for ( j = 0 ; j < pParts->GetCount() ; j++)
		{
			pPoints = pParts->Get(j); 
            k += pPoints->GetCount();
		} 
		pPolygonCount[i] = k;
		m += k;
	}
	
	pPtArray = new CPoint[m];
    if ( pPtArray == NULL )
    { 
		delete []pPolygonCount;
		return ;
	}
	
	for ( m= 0 , i = 0 ; i < pPolygon->GetCount() ; i++ )
	{
		pParts =  pPolygon->GetParts(i);
		for ( j = 0 ; j < pParts->GetCount() ; j++)
		{
			pPoints = pParts->Get(j); 
            for ( k = 0 ; k < pPoints->GetCount(); k++ )
            {
				pPoint = pPoints->Get(k); 
				pPtArray[m].x = (int)((pPoint->GetX() - draw.m_StartX)/draw.m_Scale);
                pPtArray[m++].y =  (long)((draw.m_StartY - pPoint->GetY() )/draw.m_Scale);
				
			}	
		} 
		
	}
	if ( pPolygon->GetCount() > 1)
		pDC->PolyPolygon(pPtArray,pPolygonCount,iCount); //绘制复合多边形
	else
		pDC->Polygon(pPtArray, m); 		
	delete []pPolygonCount;
	delete []pPtArray;	 					

}