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

📄 shapefile.cpp

📁 一个英国人写的GIS查看/编辑工具。支持标准的shapefile地图文件格式和coverage地图文件格式。同时可以编辑相应的dbf文件。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
   }

   mapobj.SetMapObject(NULL);
   maplayer.CArray <CMapLayerObj*,  CMapLayerObj*>::RemoveAll(); // Prevents deletion of memory

   return bOK;
}


///////////////////////////////////////////////////////////////////////////////
//
// Exports map lines in the format of a shape file
//

BOOL CShapeFile::ExportShapeFilePoly(CMapLayer* pMapLayer, LPCSTR sFileName, int nFlags)
{
   BOOL bOK = TRUE;
   CMainHeader mainheader;   
   CPolyLine polyline;
   DWORD nShape = SHPPolyLine;
   FILE* pFile = NULL;   
  
   // Retrieve query data

   BOOL bLatLon = nFlags & LatLon;
   
   if (nFlags & Polygon) nShape = nShape = SHPPolygon;

   // If polygon, make sure that the last point is closed

   if (nShape == SHPPolygon)
   {
      PolylineToPolygon(pMapLayer);
   };

  // Determine the extend of the points

   polyline = GetBoundingBox(pMapLayer, bLatLon);
   
   memset(&mainheader,0,sizeof(mainheader));      
   mainheader.m_dXMin = polyline.m_dBox[0];
   mainheader.m_dXMax = polyline.m_dBox[2];
   mainheader.m_dYMin = polyline.m_dBox[1];
   mainheader.m_dYMax = polyline.m_dBox[3];   
   
  // Initialise the polyline

   polyline.m_nParts = 0;
   polyline.m_nPoints = 0;      

  // First create the header

   mainheader.m_nFileCode = ReverseBytes(9994);      
   mainheader.m_nVersion = 1000;
   mainheader.m_nShapeType = nShape;   

   // Count the number of points, exclude repeating null values
      
   for (int j = 0; j < pMapLayer->GetSize(); j++)
   {     
      CMapLayerObj* pMapObj = pMapLayer->GetAt(j);
      if (pMapObj->GetDataType() == BDMAPLINES)
      {
         CLongLines* pMapLines = (CLongLines*)pMapObj->GetMapObject(); 

         CPolyLine polylineP = GetNumParts(pMapLines);
         polyline.m_nParts += polylineP.m_nParts;
         polyline.m_nPoints += polylineP.m_nPoints;         
      }
   };

   // Determine the file length
   
   // Support for multipart polylines
      int nFileLength = sizeof(CMainHeader) + (sizeof(CRecordHeader) + sizeof(CPolyLine) + sizeof(int)) * pMapLayer->GetSize() + 
                     sizeof(int) * polyline.m_nParts + sizeof(double)*2 * polyline.m_nPoints;

    mainheader.m_nFileLength = ReverseBytes(nFileLength/2);
     
   // Open the file as binary

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

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

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

   // Export the index file
   
   if (bOK)
   {      
      bOK = ExportIndexFile(polyline, pMapLayer, sFileName, mainheader);
   };
   
  // Export DBASE format
 
   if (bOK)
   {  
      if (pMapLayer->GetQuery() != NULL)
      {                
         bOK = ExportDBaseQuery(pMapLayer, sFileName);
      }
      else
      {  
         // Used for exporting from editor (no query)
         bOK = ExportDBase(pMapLayer, sFileName);
      } 
   };

   ASSERT(AfxCheckMemory());

   return bOK;
}

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

BOOL CShapeFile::PolylineToPolygon(CMapLayer* pMapLayer)
{
   CLongCoord coord1, coord2;

   for (int j = 0; j < pMapLayer->GetSize(); j++)
   {
      CMapLayerObj* pMapLayerObj = pMapLayer->GetAt(j);
      CLongLines* pMapLines = (CLongLines*)pMapLayerObj->GetMapObject();

      // For each map lines, close polygons
      
      for (int i = 0; i < pMapLines->GetSize(); i++)
      {
         // Determine the start of a line

         if (!pMapLines->GetAt(i).IsNull() && 
             (i == 0 || (i > 0 && pMapLines->GetAt(i-1).IsNull())))             
         {
            coord1 = pMapLines->GetAt(i);
         }

         // Determine the end of a line

         if (i + 1 < pMapLines->GetSize() && 
             pMapLines->GetAt(i+1).IsNull() &&
             !pMapLines->GetAt(i).IsNull())
         {
            coord2 = pMapLines->GetAt(i);

            // If the two ends are not the same then make them the same

            if (coord1.x != coord2.x && coord1.y != coord2.y)
            {
               pMapLines->InsertAt(i+1, coord1);  
               i++;
            }      
         }         
      }
   }  
   return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//
// Exports the polyline part of the shape file - retains multipart polylines
//

BOOL CShapeFile::ExportPolyLine(CMapLayer* pMapLayer, FILE* pFile, BOOL bLatLon, DWORD nShape)
{
   BOOL bOK = TRUE;   
   CRecordHeader recordheader;      
   CPolyLine polyline;

   // Determine parts

   int nRecord = 1;   
   for (int j = 0; j < pMapLayer->GetSize(); j++)
   {      
      BOOL bStart = TRUE;

      CMapLayerObj* pMapObj = pMapLayer->GetAt(j);
      if (pMapObj->GetDataType() == BDMAPLINES)
      {
         CLongLines* pMapLines = (CLongLines*)pMapObj->GetMapObject(); 

         // Determine bounding rectangle

         polyline = GetBoundingBoxPoly(pMapLines, bLatLon);            

         // For each polyline determine its parts

         CLongArray anParts;
         anParts.Add(0);

         polyline.m_nPoints = 0;
         for (int k = 0; k < pMapLines->GetSize(); k++)
         {
            CLongCoord coord = pMapLines->GetAt(k);
            if (!coord.IsNull()) polyline.m_nPoints++;
            else if (k + 1 < pMapLines->GetSize()) anParts.Add(polyline.m_nPoints);             
         }
         polyline.m_nParts = anParts.GetSize();         

         // Write record header

         recordheader.m_nRecordNumber = ReverseBytes(nRecord++);
         int nRecordLength = sizeof(int) + sizeof(CPolyLine) + sizeof(int)*polyline.m_nParts + 
                             sizeof(double)*2 * polyline.m_nPoints;
         recordheader.m_nContentLength = ReverseBytes(nRecordLength/2);

         fwritex(&recordheader, sizeof(CRecordHeader),1,pFile);
         
         // Write shape type

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

         // Write polyline record contents

         fwritex(&polyline, sizeof(CPolyLine),1,pFile);

         // Write the parts data

         fwritex(anParts.GetData(), sizeof(int),anParts.GetSize(),pFile);
                        
         // Write the points data         

         for (int i = 0; i < pMapLines->GetSize() && bOK; i++)
         {
            CLongCoord coord = pMapLines->GetAt(i);
            if (!coord.IsNull())
            {
               // Output the data

               double dX = coord.x;
               double dY = coord.y;

               if (bLatLon)
			      {                
				      BDProjection()->TransMercatorToLatLon(dX, dY, &dY, &dX);
               } else
               {

               };

               fwritex(&dX, sizeof(double), 1, pFile);
               fwritex(&dY, sizeof(double), 1, pFile);                  
            }
         }        
      }
   }
   
   return bOK;
}



///////////////////////////////////////////////////////////////////////////////
//
// Export an entire layer to a shape file (as points)
//

BOOL CShapeFile::ExportPoints(CMapLayer* pMapLayer, FILE* pFile, BOOL bLatLon)
{   
   BOOL bOK = TRUE;
   DWORD nShape = SHPPoint;
   CRecordHeader recordheader;      
   CShapePoint point; 

   // Determine parts

   int nRecord = 1;   
   for (int i = 0; i < pMapLayer->GetSize() && bOK; i++)
   {
      CCoord* pCoord = (CCoord*)pMapLayer->GetAt(i)->GetMapObject();      

      if (!pCoord->IsNull())
      {

         // Initialise the header

         recordheader.m_nRecordNumber = ReverseBytes(nRecord++);                              
         int nRecordLength = sizeof(CShapePoint) + sizeof(int);
         recordheader.m_nContentLength = ReverseBytes(nRecordLength/2);

         // Write the record header

         fwritex(&recordheader, sizeof(CRecordHeader),1,pFile);

         // Write the shape type

         fwritex(&nShape,sizeof(nShape),1,pFile);
   
         // Write the x,y data

         point.m_dX = pCoord->x;
         point.m_dY = pCoord->y;

         if (bLatLon)
		   {                
			   BDProjection()->TransMercatorToLatLon(point.m_dX, point.m_dY, &point.m_dY, &point.m_dX);
         } else
         {

         };
         fwritex(&point, sizeof(CShapePoint), 1, pFile);                        
      };
   }
   
   return bOK;   
}


///////////////////////////////////////////////////////////////////////////////
//
// Export the index file (points)
//

BOOL CShapeFile::ExportIndexFile(CMapLayer* pMapLayer, LPCSTR sFileName, CMainHeader& mainheader)
{
   CIndexRecord indexrecord;   
   FILE* pFile = NULL;
   BOOL bOK = TRUE;
   
   CString sIndexFile = sFileName;
   sIndexFile = sIndexFile.Left(sIndexFile.ReverseFind('.'));
   sIndexFile += ".shx";      

   TRY
   {
      pFile = fopen(sIndexFile,"wb");
      if (pFile != NULL)
      {
       // Write the header

         int nFileLength = sizeof(CMainHeader)+sizeof(CIndexRecord)*pMapLayer->GetSize();
         mainheader.m_nFileLength = ReverseBytes(nFileLength/2);
         fwritex(&mainheader, sizeof(CMainHeader),1,pFile);
         
       // Determine the indexes
         
         indexrecord.m_nOffset = ReverseBytes((sizeof(CMainHeader)-sizeof(CRecordHeader))/2);
         indexrecord.m_nContentLength = 0;

         for (int i = 0; i < pMapLayer->GetSize() && bOK; i++)
         {
            CLongCoord* pCoord = (CLongCoord*)pMapLayer->GetAt(i)->GetMapObject();      
            
            // Write record header

            indexrecord.m_nOffset = ReverseBytes(indexrecord.m_nContentLength)+
                                    ReverseBytes(indexrecord.m_nOffset) + 
                                    sizeof(CRecordHeader)/2;
            indexrecord.m_nOffset = ReverseBytes(indexrecord.m_nOffset);
                                                            
            int nRecordLength = sizeof(CShapePoint) + sizeof(int);
            indexrecord.m_nContentLength = ReverseBytes(nRecordLength/2);

            // Write the record header

            fwritex(&indexrecord, sizeof(CIndexRecord),1,pFile);                     
         }               
      } else
      {
         bOK = FALSE;
      }
   }
   CATCH (CException, ex)
   {
      bOK = FALSE;
   } END_CATCH

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

   return bOK;
}

///////////////////////////////////////////////////////////////////////////////
//
// Export the index file multi-part polygons
//


BOOL CShapeFile::ExportIndexFile(CPolyLine& polyline, CMapLayer* pMapLayer, LPCSTR sFileName, CMainHeader& mainheader)
{
   CIndexRecord indexrecord;   
   FILE* pFile = NULL;
   BOOL bOK = TRUE;
   
   CString sIndexFile = sFileName;
   sIndexFile = sIndexFile.Left(sIndexFile.ReverseFind('.'));
   sIndexFile += ".shx";      

   TRY
   {
      pFile = fopen(sIndexFile,"wb");
      if (pFile != NULL)
      {
       // Write the header

         int nFileLength = sizeof(CMainHeader)+sizeof(CIndexRecord)*pMapLayer->GetSize();
         mainheader.m_nFileLength = ReverseBytes(nFileLength/2);
         fwritex(&mainheader, sizeof(CMainHeader),1,pFile);
         
       // Determine the indexes
         
         indexrecord.m_nOffset = ReverseBytes(sizeof(CMainHeader)/2);         

         for (int j = 0; j < pMapLayer->GetSize() && bOK; j++)
         {
            CMapLayerObj* pMapObj = pMapLayer->GetAt(j);
            if (pMapObj->GetDataType() == BDMAPLINES)
            {               
               // For each polyline determine its parts

               CLongLines* pMapLines = (CLongLines*)pMapObj->GetMapObject();          
               polyline.m_nPoints = 0;
               polyline.m_nParts = 1;
               for (int k = 0; k < pMapLines->GetSize(); k++)
               {
                  CLongCoord coord = pMapLines->GetAt(k);
                  if (!coord.IsNull()) polyline.m_nPoints++;
                  else if (k + 1 < pMapLines->GetSize()) polyline.m_nParts++;
               }               
               int nRecordLength = sizeof(int) + sizeof(CPolyLine) + sizeof(int)*polyline.m_nParts + 
                                   sizeof(double)*2 * polyline.m_nPoints;

               // Write index
               indexrecord.m_nContentLength = ReverseBytes(nRecordLength/2);
              fwritex(&indexrecord, sizeof(CIndexRecord),1,pFile);         

               // Update the next index record
               
               int nOffSet = ReverseBytes(indexrecord.m_nOffset)*2 + nRecordLength + 
                  sizeof(CRecordHeader);
               indexrecord.m_nOffset = ReverseBytes(nOffSet/2);                                                                   
            } else
            {
                  bOK = FALSE;
            }
         }
      } else
      {
         bOK = FALSE;
      }
   }
   CATCH (CException, ex)
   {
      bOK = FALSE;
   } END_CATCH

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

   return bOK;
}

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

BOOL CShapeFile::ExportShapeFile(CMapLayer* pMapLayer, LPCSTR sFileName, int nFlags)
{  
   BOOL bOK = TRUE;  

   if (pMapLayer->GetSize() == 0)
   {
      AfxMessageBox(BDString(IDS_NODATALAYER));     
      return -1; // Prevents display of error message
   }


   if (pMapLayer->GetAt(0)->GetDataType() == BDMAPLINES)
   {
      bOK = ExportShapeFilePoly(pMapLayer, sFileName, nFlags);               
   };

   if (pMapLayer->GetAt(0)->GetDataType() == BDCOORD)
   {
      bOK = ExportShapeFilePoint(pMapLayer, sFileName, nFlags);               
   };

   return bOK;
};

///////////////////////////////////////////////////////////////////////////////
//
// This exports an entire layer to a shape file
//

BOOL CShapeFile::ExportShapeFilePoint(CMapLayer* pMapLayer, LPCSTR sFileName, BOOL bLatLon)
{
   BOOL bOK = TRUE;
   CMainHeader mainheader;   
   DWORD nShape = SHPPoint;
   FILE* pFile = NULL;

  // Determine the extent of the points

   CPolyLine polyline = GetBoundingBox(pMapLayer, bLatLon);

   memset(&mainheader,0,sizeof(mainheader));   
   mainheader.m_dXMin = polyline.m_dBox[0];
   mainheader.m_dXMax = polyline.m_dBox[2];
   mainheader.m_dYMin = polyline.m_dBox[1];
   mainheader.m_dYMax = polyline.m_dBox[3];
   
  // Initialise the polyline

   polyline.m_nParts = 0;
   polyline.m_nPoints = 0;      

  // First create the header

   mainheader.m_nFileCode = ReverseBytes(9994);      

⌨️ 快捷键说明

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