⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shapefile.cpp

📁 一个英国人写的GIS查看/编辑工具。支持标准的shapefile地图文件格式和coverage地图文件格式。同时可以编辑相应的dbf文件。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
   mainheader.m_nVersion = 1000;
   mainheader.m_nShapeType = nShape;   
      
   // Determine the file length

   int nPoints = 0;
   for (int i =0; i < pMapLayer->GetSize(); i++)
   {
      CCoord* pCoord = (CCoord*)pMapLayer->GetAt(i)->GetMapObject();      
      if (!pCoord->IsNull())
      {
         nPoints++;
      }
   }
   
   int nFileLength = sizeof(CMainHeader)+(sizeof(CRecordHeader)+sizeof(CShapePoint) + sizeof(int)*2)*nPoints;                                          
   mainheader.m_nFileLength = ReverseBytes(nFileLength/2);
     
   // Open the file as binary

   TRY
   {   
      pFile = fopen(sFileName, "wb");
      if (bOK && pFile != NULL)
      {
         // Write the file header

         if (fwrite(&mainheader, sizeof(CMainHeader),1,pFile) == 1)
         {         
            bOK = ExportPoints(pMapLayer, pFile, bLatLon);
         } else
         {
            bOK = FALSE;
         }
      } else
      {
         bOK = FALSE;
      }
   } CATCH(CException, ex)
   {
      bOK = FALSE;
   } END_CATCH

   if (pFile != NULL) fclose(pFile);

   // Export the index file
   
   if (bOK)
   {      
      bOK = ExportIndexFile(pMapLayer, sFileName, mainheader);
   };
   
   
  // Export DBASE format
   
   if (bOK)
   {
      if (pMapLayer->GetQuery() != NULL)
      {
         bOK = ExportDBaseQuery(pMapLayer, sFileName);
      } else
      {         
         bOK = ExportDBase(pMapLayer, sFileName);
      }
   };

   return bOK;
}

///////////////////////////////////////////////////////////////////////////////
//
// Retrieves a bounding box for an entire layer
//

CPolyLine CShapeFile::GetBoundingBox(CMapLayer* pMapLayer, BOOL bLatLon)
{   
   // Initialise polyline

   CPolyLine polyline;

   polyline.m_dBox[0] = DBL_MAX;
   polyline.m_dBox[1] = DBL_MAX;
   polyline.m_dBox[2] = -DBL_MAX;
   polyline.m_dBox[3] = -DBL_MAX;

   for (int i = 0; i < pMapLayer->GetSize(); i++)
   {
      // Map layer

      CMapLayerObj* pMapLayerObj = pMapLayer->GetAt(i);
      if (pMapLayerObj->GetDataType() == BDMAPLINES)
      {                  
         CLongLines* pMapLines = (CLongLines*)pMapLayerObj->GetMapObject();
         CPolyLine polylineP = GetBoundingBoxPoly(pMapLines, bLatLon);         

         polyline.m_dBox[0] = min(polyline.m_dBox[0], polylineP.m_dBox[0]);
         polyline.m_dBox[1] = min(polyline.m_dBox[1], polylineP.m_dBox[1]);
         polyline.m_dBox[2] = max(polyline.m_dBox[2], polylineP.m_dBox[2]);
         polyline.m_dBox[3] = max(polyline.m_dBox[3], polylineP.m_dBox[3]);
      }
      
      // Points

      else if (pMapLayerObj->GetDataType() == BDCOORD)
      {
         CCoord coord = *(CCoord*)pMapLayerObj->GetMapObject();
         
         // Convert to lat/lon if necessary         

         double dX, dY;

         if (bLatLon)
         {
            BDProjection()->TransMercatorToLatLon(coord.x, coord.y, &dY, &dX);            
         } else
         {
             dX = coord.x;
             dY = coord.y;

         }

         polyline.m_dBox[0] = min(polyline.m_dBox[0], dX);
         polyline.m_dBox[1] = min(polyline.m_dBox[1], dY);
         polyline.m_dBox[2] = max(polyline.m_dBox[2], dX);
         polyline.m_dBox[3] = max(polyline.m_dBox[3], dY);         
      }
   }   

   return polyline;
}

///////////////////////////////////////////////////////////////////////////////
//
// Retrieves the bounding box for a map line
//

CPolyLine CShapeFile::GetBoundingBoxPoly(CLongLines* pMapLines, BOOL bLatLon, int i1, int i2)
{
   CPolyLine polyline;

   if (i1 == i2) i2 = pMapLines->GetSize();
   
   polyline.m_dBox[0] = DBL_MAX;
   polyline.m_dBox[1] = DBL_MAX;
   polyline.m_dBox[2] = -DBL_MAX;
   polyline.m_dBox[3] = -DBL_MAX;

   for (int i = i1; i < i2; i++)
   {         
      CLongCoord coord = pMapLines->GetAt(i);
      if (!coord.IsNull())
      {         
         polyline.m_dBox[0] = min(polyline.m_dBox[0], coord.x);
         polyline.m_dBox[1] = min(polyline.m_dBox[1], coord.y);
         polyline.m_dBox[2] = max(polyline.m_dBox[2], coord.x);
         polyline.m_dBox[3] = max(polyline.m_dBox[3], coord.y);
      };         
   }

   // Convert to lat/lon if necessary         

   if (bLatLon)
   {
      BDProjection()->TransMercatorToLatLon(polyline.m_dBox[0], polyline.m_dBox[1], 
                            &polyline.m_dBox[1], &polyline.m_dBox[0]);
      BDProjection()->TransMercatorToLatLon(polyline.m_dBox[2], polyline.m_dBox[3], 
                            &polyline.m_dBox[3], &polyline.m_dBox[2]);

      // Swap if min > max

      if (polyline.m_dBox[0] > polyline.m_dBox[2])
      {
         double d = polyline.m_dBox[0];
         polyline.m_dBox[0] = polyline.m_dBox[2];
         polyline.m_dBox[2] = d;
      }
   } else
   {

   }

   return polyline;
}

///////////////////////////////////////////////////////////////////////////////

CPolyLine CShapeFile::GetNumParts(CLongLines* pMapLines)
{
   CPolyLine polyline;

   BOOL bStart = TRUE;
   for (int i = 0; i < pMapLines->GetSize(); i++)
   {
      CLongCoord coord = pMapLines->GetAt(i);
      if (coord.IsNull())
      {
         bStart = TRUE;                  
      }
      else
      {
         if (bStart) polyline.m_nParts++;
         polyline.m_nPoints++;      
         bStart = FALSE;
      }
   } 
   return polyline;
}

///////////////////////////////////////////////////////////////////////////////
//
// Determines the text to be exported with the object
//

CString CShapeFile::GetLineText(CMapLayer* pMapLayer, CMapLayerObj* pMapLayerObj)
{
   if (pMapLayer->GetSepColour())
   {
      for (int i = 0; i < pMapLayer->GetMapProp().m_aColourFeature.GetSize(); i++)
      {
         CColourFeature &rColourFeature = pMapLayer->GetMapProp().m_aColourFeature.GetAt(i);

         if (pMapLayer->GetSepColour() == CMapLayer::SepColourFeature)
         {           
            if (rColourFeature.m_lFeatureId == pMapLayerObj->GetFeature())
            {
               return rColourFeature.m_sFeature;               
            }
         } else
         {
            if (rColourFeature.m_sAttr == pMapLayerObj->GetText())
            {
               return rColourFeature.m_sFeature;               
            }
         }
      }
      return "";
   } else
   {
      return pMapLayerObj->GetText();
   }
}

///////////////////////////////////////////////////////////////////////////////
//
// Export the dbase data for shapefile.  For NRDBPro,  this includes ALL 
// columns from the query
//

BOOL CShapeFile::ExportDBaseQuery(CMapLayer* pMapLayer, LPCSTR sFileName)
{
   BOOL bOK = TRUE;
   CDBFHeader header;
   CDBFDescriptor descriptor;   

   CQuery* pQuery = pMapLayer->GetQuery();

   // Retrieve data

   CDlgProgress dlg;   

   CQueryResult queryresult;
   if (!queryresult.Initialise(pQuery) || 
       queryresult.GetSize() == 0)
   {
      bOK = FALSE;
   }
   
   // Create file name

   CString sIndexFile = sFileName;
   sIndexFile = sIndexFile.Left(sIndexFile.ReverseFind('.'));
   sIndexFile += ".dbf";      

   FILE* pFile = fopen(sIndexFile,"wb");
     
   TRY
   {

      if (bOK && pFile != NULL)
      {

         // Create header
   
         CDateTime date;
         date.AsSystemDate();
         memset(&header, 0, sizeof(header));
         header.m_nValid = 0x03;
         header.m_aDate[0] = date.GetYear()%100+100;
         header.m_aDate[1] = date.GetMonth();
         header.m_aDate[2] = date.GetDay();
         
         header.m_nNumRecords = pMapLayer->GetSize();
         
         // Determine number of record bytes and fields

         CAttrArray& aAttr = *queryresult.GetAt(0);
         int nRecordBytes = 0;
         int nFields = 0;

         for (int i = 0; i < aAttr.GetSize(); i++)
         {
            switch (aAttr[i]->GetDataType())
            {
			      case BDTEXT : case BDLINK : case BDFEATURE : case BDFTYPE : case BDLONGTEXT :
                 nRecordBytes += DBF_TEXT; nFields++; break;
               case BDBOOLEAN : nRecordBytes += DBF_BOOL; nFields++; break;
               case BDNUMBER : nRecordBytes += DBF_NUMBER; nFields++; break;
               case BDDATE : nRecordBytes += DBF_DATE; nFields++; break;
            }
          
         }      

         // Set number of field descriptor bytes
      
         header.m_nHeaderBytes = sizeof(header) + sizeof(CDBFDescriptor) *
            nFields + sizeof(BYTE);
         header.m_nRecordBytes = nRecordBytes + sizeof(BYTE);   

         header.m_nReserved3[1] = 0;

         fwritex(&header,sizeof(header),1,pFile);

         // Create the record descriptors
      
         for (i = 0; i < aAttr.GetSize(); i++)
         {
           memset(&descriptor,0,sizeof(descriptor));
           strncpy(descriptor.m_sName, aAttr[i]->GetDesc(), 10);

           switch (aAttr[i]->GetDataType())
           {
		       case BDTEXT : case BDLINK : case BDFEATURE : case BDFTYPE : case BDLONGTEXT :
                  descriptor.m_nType = 'C';
                  descriptor.m_nFieldLength = DBF_TEXT;
                  break;
               case BDNUMBER : 
                  descriptor.m_nType = 'N';
                  descriptor.m_nFieldLength = DBF_NUMBER;
                  descriptor.m_nFieldCount = DBF_NDP;
                  break;
               case BDDATE : 
                  descriptor.m_nType = 'D';
                  descriptor.m_nFieldLength = DBF_DATE;
                  break;
               case BDBOOLEAN :
                  descriptor.m_nType = 'L';
                  descriptor.m_nFieldLength = DBF_BOOL;
                  break;
           }
           if (descriptor.m_nType != 0)
           {
              fwritex(&descriptor,sizeof(descriptor),1,pFile);
           }
        }

        BYTE nTerminator = 0x0D;
        fwritex(&nTerminator,sizeof(BYTE),1,pFile);         

        // Write the data

        for (i = 0; i < queryresult.GetSize(); i++)
        {
           CAttrArray &aAttr = *queryresult.GetAt(i);

           if (IsValidMapObject(aAttr, queryresult.GetAttrArray()))
           {                       
              // Write the record separator

              BYTE nRecord = 0x20;
              fwritex(&nRecord,sizeof(BYTE),1,pFile);

              // Write the attribute data

              for (int j = 0; j < aAttr.GetSize(); j++)
              {
                 CString s;
                 char record[DBF_TEXT];              
                 memset(&record, 0x20, sizeof(record));

                 CAttribute* pAttr = aAttr.GetAt(j);

                 int nLength = 0;
                 switch(pAttr->GetDataType())
                 {
			        case BDTEXT : case BDLINK : case BDFEATURE : case BDFTYPE : case BDLONGTEXT :
                       s = pAttr->AsString();
                       strncpy(record, s, min(DBF_TEXT, s.GetLength()));
                       nLength = DBF_TEXT;
                       break;
                    case BDNUMBER :
                       if (!pAttr->IsNull())
                       {
                          s.Format("%*lf", DBF_NUMBER, *pAttr->GetDouble());
                       } else
                       {
                          s = "";
                       }
                       strncpy(record, s, DBF_NUMBER);
                       nLength = DBF_NUMBER;
                       break;
                    case BDBOOLEAN : 
                       if (*pAttr->GetBoolean() == TRUE) record[0] = 'Y';
                       else if (*pAttr->GetBoolean() == FALSE) record[0] = 'N';
                       else record[0] = '?';
                       nLength = DBF_BOOL;
                       break;
                    case BDDATE :                    
                       CDateTime date(*pAttr->GetDate(), 0);      
                       CString s1,s2;
                       s.Format("%4d",date.GetYear());                     
                       if (date.GetMonth() != 0) s1.Format("%02d",date.GetMonth());                     
                       if (date.GetDay() != 0)  s2.Format("%02d",date.GetDay());                        
                       s += s1 + s2;
                       strncpy(record, s, min(DBF_DATE, s.GetLength()));
                       nLength = DBF_DATE;
                       break;
                 }
                 if (nLength != 0) fwritex(&record, nLength, 1, pFile);
              }                                                          
           }
        }     
        // Write the end of record

        BYTE nEnd = 0x1a;
        fwritex(&nEnd, sizeof(nEnd), 1, pFile);                    
      } else
      {
         bOK = FALSE;
      }

   } CATCH(CException, ex)
   {      
      bOK = FALSE;
   } END_CATCH

   if (pFile != NULL) fclose(pFile);

   return bOK;
}

///////////////////////////////////////////////////////////////////////////////
//
// Export the dbase data for shapefile
//

BOOL CShapeFile::ExportDBase(CMapLayer* pMapLayer, LPCSTR sFileName)
{
   BOOL bOK = TRUE;
   CDBFHeader header;
   CDBFDescriptor aDescriptor[2];
   CDBFRecordPoint record;

   // Create file name

   CString sIndexFile = sFileName;
   sIndexFile = sIndexFile.Left(sIndexFile.ReverseFind('.'));
   sIndexFile += ".dbf";      

   // Create header
   
   memset(&header, 0, sizeof(header));
  
   header.m_nValid = 0x03;

   // Set update date
   CDateTime date;
   date.AsSystemDate();
   header.m_aDate[0] = date.GetYear()%100+100;
   header.m_aDate[1] = date.GetMonth();
   header.m_aDate[2] = date.GetDay();   

   header.m_nNumRecords = pMapLayer->GetSize();
   header.m_nHeaderBytes = sizeof(header) + sizeof(aDescriptor)+sizeof(BYTE);
   header.m_nRecordBytes = sizeof(CDBFRecordPoint)+1;   
   header.m_nReserved3[1] = 0;

   // Create the record descriptors

   memset(aDescriptor,0,sizeof(aDescriptor));
   memcpy(aDescriptor[0].m_sName,"ID",2);
   aDescriptor[0].m_nType = 'N';
   aDescriptor[0].m_nFieldLength = 0x08;
   
   memcpy(aDescriptor[1].m_sName,"NAME",4);
   aDescriptor[1].m_nType = 'C';
   aDescriptor[1].m_nFieldLength = 0x20;

   BYTE nTerminator = 0x0D;
   BYTE nRecord = 0x20;
   BYTE nEnd = 0x1a;

   // Create the data field

   memset(&record,0x20,sizeof(CDBFRecordPoint));
   
   FILE* pFile = fopen(sIndexFile,"wb");
   if (pFile != NULL)
   {
      // Write header

      if (fwrite(&header,sizeof(header),1,pFile) == 1)
      {
         // Write record descriptors

         for (int i = 0; i < sizeof(aDescriptor)/sizeof(CDBFDescriptor) && bOK; i++)
         {
            if (fwrite(&aDescriptor[i],sizeof(CDBFDescriptor),1,pFile) != 1)
            {
               bOK = FALSE;
            }
         }

         // Write field terminator

         if (bOK && fwrite(&nTerminator,sizeof(BYTE),1,pFile) != 1)
         {
            bOK = FALSE;
         }

         // Write the data

         int nLabel = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -