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