📄 shapefile.cpp
字号:
}
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 + -