






















#include "ShapefileEditor.h" #include <map> #include <cassert> //#include <sys/stat.h> // 用于检测文件是否存在(跨平台简易方式) #include <stdexcept> #include <fstream> #include <iostream> #include <locale> #include <codecvt> #ifdef _WIN32 #include <windows.h> #endif using namespace VRE; // 单例实例获取 ShapefileTool& ShapefileTool::GetInstance(Encoding encoding) { static ShapefileTool instance(encoding); return instance; } // 私有构造函数 ShapefileTool::ShapefileTool(Encoding encoding) : m_dataset(nullptr), m_layer(nullptr), m_opened(false), m_spatialRef(nullptr), m_autoCalcFields(true), m_encoding(encoding), m_lastError("") { InitGDAL(); SetGDALEncoding(); } ShapefileTool::~ShapefileTool() { Close(); CleanupGDAL(); } bool ShapefileTool::CheckFilePath(const std::string& filename) { if (filename.empty()) { m_lastError = "文件路径为空"; return false; } // 检查文件路径是否包含非法字符 if (filename.find("..") != std::string::npos) { m_lastError = "文件路径包含非法字符 '..'"; return false; } // 检查文件扩展名 if (filename.length() < 4 || filename.substr(filename.length() - 4) != ".shp") { m_lastError = "文件扩展名必须是 .shp"; return false; } return true; } std::string ShapefileTool::GetLastError() const { return m_lastError; } std::string ShapefileTool::ConvertFilePath(const std::string& filename) const { #ifdef _WIN32 // 在Windows上,GDAL 2.2.3需要GBK编码的路径 if (m_encoding == GBK) { return filename; // 如果已经是GBK,直接返回 } // 如果是UTF-8,转换为GBK if (m_encoding == UTF8) { std::wstring_convert<std::codecvt_utf8<wchar_t>> conv; try { std::wstring wstr = conv.from_bytes(filename); int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), (int)wstr.size(), nullptr, 0, nullptr, nullptr); std::string gbk_str(size_needed, 0); WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), (int)wstr.size(), &gbk_str[0], size_needed, nullptr, nullptr); return gbk_str; } catch (...) { // 如果转换失败,返回原路径 return filename; } } #endif // 其他平台或编码直接返回 return filename; } void ShapefileTool::InitGDAL() { static bool initialized = false; if (!initialized) { GDALAllRegister(); // 针对GDAL 2.2.3的中文路径问题,设置文件名编码为系统默认 CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); initialized = true; } } void ShapefileTool::CleanupGDAL() { // 注意:不要在这里调用 GDALDestroyDriverManager(); // 因为这会影响程序中其他使用GDAL的组件 } void ShapefileTool::SetGDALEncoding() const { switch (m_encoding) { case UTF8: CPLSetConfigOption("SHAPE_ENCODING", "UTF-8"); break; case GBK: CPLSetConfigOption("SHAPE_ENCODING", "GBK"); break; case SYSTEM: default: CPLSetConfigOption("SHAPE_ENCODING", ""); break; } } std::string ShapefileTool::UTF8ToGBK(const std::string& utf8Str) const { if (utf8Str.empty()) return ""; int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, nullptr, 0); if (wlen == 0) return utf8Str; std::wstring wstr(wlen, 0); MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wstr[0], wlen); int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); if (len == 0) return utf8Str; std::string gbkStr(len, 0); WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &gbkStr[0], len, nullptr, nullptr); // 去除末尾的null字符 if (!gbkStr.empty() && gbkStr[gbkStr.size() - 1] == '\0') { gbkStr.resize(gbkStr.size() - 1); } return gbkStr; } std::string ShapefileTool::GBKToUTF8(const std::string& gbkStr) const { if (gbkStr.empty()) return ""; int wlen = MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, nullptr, 0); if (wlen == 0) return gbkStr; std::wstring wstr(wlen, 0); MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, &wstr[0], wlen); int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); if (len == 0) return gbkStr; std::string utf8Str(len, 0); WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &utf8Str[0], len, nullptr, nullptr); // 去除末尾的null字符 if (!utf8Str.empty() && utf8Str[utf8Str.size() - 1] == '\0') { utf8Str.resize(utf8Str.size() - 1); } return utf8Str; } std::string ShapefileTool::ConvertEncoding(const std::string& str) const { if (str.empty()) return str; // 根据当前编码设置进行转换 switch (m_encoding) { case UTF8: // 如果已经是UTF-8,直接返回 return str; case GBK: #ifdef _WIN32 // 在Windows上,将UTF-8转换为GBK return UTF8ToGBK(str); #else // 在其他平台上,GBK可能不被支持,返回原字符串 return str; #endif case SYSTEM: default: #ifdef _WIN32 // 在Windows系统上,默认使用GBK return UTF8ToGBK(str); #else // 在其他系统上,使用UTF-8 return str; #endif } } bool ShapefileTool::Open(const char* filename, bool update) { return Open(std::string(filename), update); } bool ShapefileTool::Open(const std::string& filename, bool update) { Close(); if (!CheckFilePath(filename)) { return false; } // 设置编码 SetGDALEncoding(); // 转换文件路径编码 std::string convertedPath = ConvertFilePath(filename); m_dataset = (GDALDataset*)GDALOpenEx(convertedPath.c_str(), update ? GDAL_OF_UPDATE | GDAL_OF_VECTOR : GDAL_OF_READONLY | GDAL_OF_VECTOR, nullptr, nullptr, nullptr); if (!m_dataset) { m_lastError = std::string("无法打开文件: ") + filename + ",错误: " + CPLGetLastErrorMsg(); return false; } m_layer = m_dataset->GetLayer(0); if (!m_layer) { m_lastError = std::string("无法获取图层: ") + filename; Close(); return false; } // 获取坐标系信息 if (m_layer->GetSpatialRef()) { m_spatialRef = m_layer->GetSpatialRef()->Clone(); } m_opened = true; return true; } bool ShapefileTool::Create(const char* filename, OGRwkbGeometryType geomType, const std::vector<std::pair<std::string, OGRFieldType>>& fields, CoordinateSystem coordSystem, bool autoCalcFields) { return Create(std::string(filename), geomType, fields, coordSystem, autoCalcFields); } bool ShapefileTool::Create(const std::string& filename, OGRwkbGeometryType geomType, const std::vector<std::pair<std::string, OGRFieldType>>& fields, CoordinateSystem coordSystem, bool autoCalcFields) { // 创建坐标系 OGRSpatialReference* spatialRef = CreateSpatialReference(coordSystem); if (!spatialRef) { m_lastError = "创建坐标系失败"; return false; } bool result = CreateWithSpatialRef(filename, geomType, fields, spatialRef, autoCalcFields); // 注意:CreateWithSpatialRef会接管spatialRef的内存管理 // 如果创建失败,需要手动删除 if (!result) { delete spatialRef; } return result; } bool ShapefileTool::CreateWithSpatialRef(const char* filename, OGRwkbGeometryType geomType, const std::vector<std::pair<std::string, OGRFieldType>>& fields, OGRSpatialReference* spatialRef, bool autoCalcFields) { return CreateWithSpatialRef(std::string(filename), geomType, fields, spatialRef, autoCalcFields); } bool ShapefileTool::CreateWithSpatialRef(const std::string& filename, OGRwkbGeometryType geomType, const std::vector<std::pair<std::string, OGRFieldType>>& fields, OGRSpatialReference* spatialRef, bool autoCalcFields) { Close(); if (!CheckFilePath(filename)) { return false; } // 设置编码 SetGDALEncoding(); // 转换文件路径编码 std::string convertedPath = ConvertFilePath(filename); // 获取ESRI Shapefile驱动 GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("ESRI Shapefile"); if (!driver) { m_lastError = "无法获取ESRI Shapefile驱动"; return false; } // 检查驱动是否支持创建操作 char** driverMetadata = driver->GetMetadata(); if (!CSLFetchBoolean(driverMetadata, GDAL_DCAP_CREATE, FALSE)) { m_lastError = "驱动不支持创建操作"; return false; } // 删除已存在文件 CPLErr err = driver->Delete(convertedPath.c_str()); // 清除错误状态 CPLErrorReset(); // 创建数据集 m_dataset = driver->Create(convertedPath.c_str(), 0, 0, 0, GDT_Unknown, nullptr); if (!m_dataset) { m_lastError = std::string("创建数据集失败: ") + CPLGetLastErrorMsg(); return false; } // 设置坐标系 - 克隆传入的spatialRef if (spatialRef) { m_spatialRef = spatialRef->Clone(); if (!m_spatialRef) { m_lastError = "克隆空间参考系统失败"; Close(); return false; } } else { // 如果没有提供spatialRef,使用WGS84作为默认 m_spatialRef = CreateSpatialReference(WGS84); if (!m_spatialRef) { m_lastError = "创建默认坐标系失败"; Close(); return false; } } m_autoCalcFields = autoCalcFields; // 创建图层 m_layer = m_dataset->CreateLayer("layer", m_spatialRef, geomType, nullptr); if (!m_layer) { m_lastError = std::string("创建图层失败: ") + CPLGetLastErrorMsg(); Close(); return false; } // 创建字段 for (const auto& field : fields) { // 转换字段名编码 std::string encodedFieldName = ConvertEncoding(field.first); OGRFieldDefn fieldDefn(encodedFieldName.c_str(), field.second); if (m_layer->CreateField(&fieldDefn) != OGRERR_NONE) { m_lastError = std::string("创建字段失败: ") + field.first; Close(); return false; } } // 自动添加几何字段 if (m_autoCalcFields) { if (!AddGeometryFields(geomType)) { m_lastError = "添加几何字段失败"; Close(); return false; } } m_opened = true; // 生成.prj文件 return CreatePrjFile(filename.c_str()); } int ShapefileTool::GetFeatureCount() { if (!m_opened || !m_layer) return 0; return (int)m_layer->GetFeatureCount(); } OGRFeature* ShapefileTool::GetFeature(int id) { if (!m_opened || !m_layer) return nullptr; return m_layer->GetFeature(id); } bool ShapefileTool::SetGeometry(int id, OGRGeometry* geometry) { if (!m_opened || !m_layer) { if (geometry) OGRGeometryFactory::destroyGeometry(geometry); return false; } OGRFeature* feature = m_layer->GetFeature(id); if (!feature) { if (geometry) OGRGeometryFactory::destroyGeometry(geometry); return false; } OGRErr err = feature->SetGeometry(geometry); if (err != OGRERR_NONE) { OGRFeature::DestroyFeature(feature); if (geometry) OGRGeometryFactory::destroyGeometry(geometry); return false; } // 自动计算几何字段 if (m_autoCalcFields) { CalculateAndSetGeometryFields(feature, geometry); } bool result = (m_layer->SetFeature(feature) == OGRERR_NONE); OGRFeature::DestroyFeature(feature); // 几何对象由OGRFeature接管,不需要手动销毁 return result; } bool ShapefileTool::SetField(int id, const char* fieldName, const char* value) { return SetField(id, fieldName, std::string(value)); } bool ShapefileTool::SetField(int id, const char* fieldName, const std::string& value) { if (!m_opened || !m_layer) return false; OGRFeature* feature = m_layer->GetFeature(id); if (!feature) return false; // 转换编码 std::string encodedValue = ConvertEncoding(value); feature->SetField(fieldName, encodedValue.c_str()); bool result = (m_layer->SetFeature(feature) == OGRERR_NONE); OGRFeature::DestroyFeature(feature); return result; } bool ShapefileTool::SetField(int id, const char* fieldName, int value) { if (!m_opened || !m_layer) return false; OGRFeature* feature = m_layer->GetFeature(id); if (!feature) return false; feature->SetField(fieldName, value); bool result = (m_layer->SetFeature(feature) == OGRERR_NONE); OGRFeature::DestroyFeature(feature); return result; } bool ShapefileTool::SetField(int id, const char* fieldName, double value) { if (!m_opened || !m_layer) return false; OGRFeature* feature = m_layer->GetFeature(id); if (!feature) return false; feature->SetField(fieldName, value); bool result = (m_layer->SetFeature(feature) == OGRERR_NONE); OGRFeature::DestroyFeature(feature); return result; } int ShapefileTool::AddFeature(OGRGeometry* geometry, const std::vector<std::pair<std::string, std::string>>& attributes) { if (!m_opened || !m_layer) { if (geometry) OGRGeometryFactory::destroyGeometry(geometry); return -1; } OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn()); if (!feature) { if (geometry) OGRGeometryFactory::destroyGeometry(geometry); return -1; } // 设置几何 if (geometry) { OGRErr err = feature->SetGeometry(geometry); if (err != OGRERR_NONE) { OGRFeature::DestroyFeature(feature); OGRGeometryFactory::destroyGeometry(geometry); return -1; } } // 设置属性 - 这里需要确保编码转换 for (const auto& attr : attributes) { // 转换编码 std::string encodedValue = ConvertEncoding(attr.second); feature->SetField(attr.first.c_str(), encodedValue.c_str()); } // 自动计算几何字段 if (m_autoCalcFields && geometry) { CalculateAndSetGeometryFields(feature, geometry); } // 添加要素 if (m_layer->CreateFeature(feature) != OGRERR_NONE) { OGRFeature::DestroyFeature(feature); return -1; } int fid = (int)feature->GetFID(); OGRFeature::DestroyFeature(feature); return fid; } bool ShapefileTool::CopyAttributes(int sourceId, int targetId) { if (!m_opened || !m_layer) return false; OGRFeature* sourceFeature = m_layer->GetFeature(sourceId); OGRFeature* targetFeature = m_layer->GetFeature(targetId); if (!sourceFeature || !targetFeature) { if (sourceFeature) OGRFeature::DestroyFeature(sourceFeature); if (targetFeature) OGRFeature::DestroyFeature(targetFeature); return false; } // 复制所有属性字段 int fieldCount = sourceFeature->GetFieldCount(); for (int i = 0; i < fieldCount; i++) { OGRFieldDefn* fieldDefn = sourceFeature->GetFieldDefnRef(i); if (fieldDefn) { switch (fieldDefn->GetType()) { case OFTInteger: targetFeature->SetField(i, sourceFeature->GetFieldAsInteger(i)); break; case OFTReal: targetFeature->SetField(i, sourceFeature->GetFieldAsDouble(i)); break; case OFTString: default: // 对于字符串字段,获取原始值并重新设置(确保编码正确) const char* strValue = sourceFeature->GetFieldAsString(i); if (strValue) { std::string encodedValue = ConvertEncoding(strValue); targetFeature->SetField(i, encodedValue.c_str()); } break; } } } bool result = (m_layer->SetFeature(targetFeature) == OGRERR_NONE); OGRFeature::DestroyFeature(sourceFeature); OGRFeature::DestroyFeature(targetFeature); return result; } bool ShapefileTool::Save() { if (!m_opened || !m_dataset) return false; GDALFlushCache(m_dataset); return true; } void ShapefileTool::Close() { if (m_dataset) { GDALClose(m_dataset); m_dataset = nullptr; m_layer = nullptr; } m_opened = false; } OGRPoint* ShapefileTool::CreatePoint(const SVREVector3& point) { return new OGRPoint(point.lon, point.lat, point.alt); } OGRLineString* ShapefileTool::CreateLineString(const VVREGeoPoint& points) { if (points.empty()) return nullptr; OGRLineString* line = new OGRLineString(); for (const auto& point : points) { line->addPoint(point.lon, point.lat, point.alt); } return line; } OGRPolygon* ShapefileTool::CreatePolygon(const std::vector<VVREGeoPoint>& rings) { if (rings.empty()) return nullptr; OGRPolygon* polygon = new OGRPolygon(); for (size_t i = 0; i < rings.size(); i++) { const auto& ringPoints = rings[i]; if (ringPoints.size() < 3) { delete polygon; return nullptr; } OGRLinearRing* ring = new OGRLinearRing(); for (const auto& point : ringPoints) { ring->addPoint(point.lon, point.lat, point.alt); } // 闭合环(如果首尾不相等) if (ring->getNumPoints() > 0) { OGRPoint first, last; ring->getPoint(0, &first); ring->getPoint(ring->getNumPoints() - 1, &last); if (first.getX() != last.getX() || first.getY() != last.getY() || first.getZ() != last.getZ()) { ring->addPoint(first.getX(), first.getY(), first.getZ()); } } if (i == 0) { polygon->addRingDirectly(ring); // 外环 } else { polygon->addRing(ring); // 内环 } } return polygon; } SVREVector3 ShapefileTool::ConvertToVVREPoint(OGRGeometry* geometry) { SVREVector3 point; if (!geometry) return point; OGRPoint* ogrPoint = dynamic_cast<OGRPoint*>(geometry); if (ogrPoint) { point.lon = ogrPoint->getX(); point.lat = ogrPoint->getY(); point.alt = ogrPoint->getZ(); } return point; } VVREGeoPoint ShapefileTool::ConvertToVVRELineString(OGRGeometry* geometry) { VVREGeoPoint points; if (!geometry) return points; OGRLineString* lineString = dynamic_cast<OGRLineString*>(geometry); if (lineString) { int pointCount = lineString->getNumPoints(); for (int i = 0; i < pointCount; i++) { OGRPoint point; lineString->getPoint(i, &point); points.push_back(SVREVector3(point.getX(), point.getY(), point.getZ())); } } return points; } std::vector<VVREGeoPoint> ShapefileTool::ConvertToVVREPolygon(OGRGeometry* geometry) { std::vector<VVREGeoPoint> rings; if (!geometry) return rings; OGRPolygon* polygon = dynamic_cast<OGRPolygon*>(geometry); if (polygon) { // 外环 OGRLinearRing* exteriorRing = polygon->getExteriorRing(); if (exteriorRing) { VVREGeoPoint exteriorPoints; int pointCount = exteriorRing->getNumPoints(); for (int i = 0; i < pointCount; i++) { OGRPoint point; exteriorRing->getPoint(i, &point); exteriorPoints.push_back(SVREVector3(point.getX(), point.getY(), point.getZ())); } rings.push_back(exteriorPoints); } // 内环 int interiorRingCount = polygon->getNumInteriorRings(); for (int i = 0; i < interiorRingCount; i++) { OGRLinearRing* interiorRing = polygon->getInteriorRing(i); if (interiorRing) { VVREGeoPoint interiorPoints; int pointCount = interiorRing->getNumPoints(); for (int j = 0; j < pointCount; j++) { OGRPoint point; interiorRing->getPoint(j, &point); interiorPoints.push_back(SVREVector3(point.getX(), point.getY(), point.getZ())); } rings.push_back(interiorPoints); } } } return rings; } bool ShapefileTool::SetCoordinateSystem(CoordinateSystem coordSystem) { if (!m_opened || !m_layer) return false; OGRSpatialReference* spatialRef = CreateSpatialReference(coordSystem); if (!spatialRef) return false; // 设置图层的空间参考 if (m_layer->GetSpatialRef()) { delete m_spatialRef; } m_spatialRef = spatialRef; // 重新生成.prj文件 if (m_dataset) { const char* filename = m_dataset->GetDescription(); return CreatePrjFile(filename); } return false; } bool ShapefileTool::SetSpatialReference(OGRSpatialReference* spatialRef) { if (!m_opened || !m_layer || !spatialRef) return false; if (m_spatialRef) { delete m_spatialRef; } m_spatialRef = spatialRef->Clone(); // 重新生成.prj文件 if (m_dataset) { const char* filename = m_dataset->GetDescription(); return CreatePrjFile(filename); } return false; } std::string ShapefileTool::GetProjectionWKT() { if (!m_spatialRef) return ""; char* wkt = nullptr; m_spatialRef->exportToWkt(&wkt); if (wkt) { std::string result(wkt); CPLFree(wkt); return result; } return ""; } OGRSpatialReference* ShapefileTool::CreateSpatialReference(CoordinateSystem coordSystem) { OGRSpatialReference* spatialRef = new OGRSpatialReference(); switch (coordSystem) { case WGS84: spatialRef->SetWellKnownGeogCS("WGS84"); break; case WebMercator: spatialRef->importFromEPSG(3857); // Web Mercator break; case UTM_WGS84_50N: spatialRef->importFromEPSG(32650); // UTM Zone 50N, WGS84 break; default: delete spatialRef; return nullptr; } return spatialRef; } bool ShapefileTool::CreatePrjFile(const char* filename) { if (!m_spatialRef) return false; // 生成.prj文件路径 std::string prjFilename = filename; size_t dotPos = prjFilename.find_last_of('.'); if (dotPos != std::string::npos) { prjFilename = prjFilename.substr(0, dotPos); } prjFilename += ".prj"; // 转换文件路径编码 std::string convertedPrjPath = ConvertFilePath(prjFilename); // 导出为WKT格式 char* wkt = nullptr; m_spatialRef->exportToWkt(&wkt); if (!wkt) { return false; } // 写入.prj文件 std::ofstream prjFile(convertedPrjPath, std::ios::binary); if (!prjFile.is_open()) { CPLFree(wkt); return false; } prjFile << wkt; prjFile.close(); CPLFree(wkt); return true; } bool ShapefileTool::AddGeometryFields(OGRwkbGeometryType geomType) { if (!m_layer) return false; // 根据几何类型添加相应的字段 switch (wkbFlatten(geomType)) { case wkbLineString: case wkbMultiLineString: { // 为线数据添加长度字段 OGRFieldDefn lengthField("Length", OFTReal); lengthField.SetWidth(12); lengthField.SetPrecision(2); if (m_layer->CreateField(&lengthField) != OGRERR_NONE) { return false; } break; } case wkbPolygon: case wkbMultiPolygon: { // 为面数据添加面积字段 OGRFieldDefn areaField("Area", OFTReal); areaField.SetWidth(15); areaField.SetPrecision(2); if (m_layer->CreateField(&areaField) != OGRERR_NONE) { return false; } break; } default: // 点数据不需要特殊字段 break; } return true; } bool ShapefileTool::CalculateAndSetGeometryFields(OGRFeature* feature, OGRGeometry* geometry) { if (!feature || !geometry) return false; OGRwkbGeometryType geomType = wkbFlatten(geometry->getGeometryType()); switch (geomType) { case wkbLineString: case wkbMultiLineString: { // 计算线长度 double length = CalculateGeodesicLength(geometry); int fieldIndex = feature->GetFieldIndex("Length"); if (fieldIndex >= 0) { feature->SetField(fieldIndex, length); } break; } case wkbPolygon: case wkbMultiPolygon: { // 计算面面积 double area = CalculateGeodesicArea(geometry); int fieldIndex = feature->GetFieldIndex("Area"); if (fieldIndex >= 0) { feature->SetField(fieldIndex, area); } break; } default: break; } return true; } double ShapefileTool::CalculateGeodesicLength(OGRGeometry* geometry) { if (!geometry) return 0.0; double totalLength = 0.0; // 处理不同类型的线几何 OGRwkbGeometryType geomType = wkbFlatten(geometry->getGeometryType()); if (geomType == wkbLineString) { OGRLineString* line = (OGRLineString*)geometry; // 创建用于测地线计算的几何对象 OGRGeometry* geodesicGeometry = line->clone(); if (geodesicGeometry) { // 如果是在地理坐标系中,使用测地线计算 if (m_spatialRef && m_spatialRef->IsGeographic()) { // 转换为测地线长度(米) totalLength = line->get_Length(); // 对于地理坐标系,需要将度转换为米(近似) // 这里使用赤道处1度≈111.32km的近似值 // 实际应用中可以使用更精确的椭球体计算方法 totalLength *= 111320.0; // 1度 ≈ 111.32km } else { // 投影坐标系直接使用长度 totalLength = line->get_Length(); } OGRGeometryFactory::destroyGeometry(geodesicGeometry); } } else if (geomType == wkbMultiLineString) { OGRMultiLineString* multiLine = (OGRMultiLineString*)geometry; for (int i = 0; i < multiLine->getNumGeometries(); i++) { totalLength += CalculateGeodesicLength(multiLine->getGeometryRef(i)); } } return totalLength; } double ShapefileTool::CalculateGeodesicArea(OGRGeometry* geometry) { if (!geometry) return 0.0; double totalArea = 0.0; // 处理不同类型的面几何 OGRwkbGeometryType geomType = wkbFlatten(geometry->getGeometryType()); if (geomType == wkbPolygon) { OGRPolygon* polygon = (OGRPolygon*)geometry; // 创建用于测地线计算的几何对象 OGRGeometry* geodesicGeometry = polygon->clone(); if (geodesicGeometry) { // 如果是在地理坐标系中,使用测地线计算 if (m_spatialRef && m_spatialRef->IsGeographic()) { // 转换为测地线面积(平方米) totalArea = polygon->get_Area(); // 对于地理坐标系,需要将平方度转换为平方米(近似) // 这里使用赤道处1平方度≈12,355km²的近似值 // 实际应用中可以使用更精确的椭球体计算方法 totalArea *= 12355000000.0; // 1平方度 ≈ 12,355km² } else { // 投影坐标系直接使用面积 totalArea = polygon->get_Area(); } OGRGeometryFactory::destroyGeometry(geodesicGeometry); } } else if (geomType == wkbMultiPolygon) { OGRMultiPolygon* multiPolygon = (OGRMultiPolygon*)geometry; for (int i = 0; i < multiPolygon->getNumGeometries(); i++) { totalArea += CalculateGeodesicArea(multiPolygon->getGeometryRef(i)); } } return totalArea; } bool ShapefileTool::RecalculateGeometryFields() { if (!m_opened || !m_layer || !m_autoCalcFields) return false; // 重置读取位置 m_layer->ResetReading(); OGRFeature* feature; bool success = true; // 遍历所有要素并重新计算几何字段 while ((feature = m_layer->GetNextFeature()) != nullptr) { OGRGeometry* geometry = feature->GetGeometryRef(); if (geometry) { if (!CalculateAndSetGeometryFields(feature, geometry)) { success = false; } // 更新要素 if (m_layer->SetFeature(feature) != OGRERR_NONE) { success = false; } } OGRFeature::DestroyFeature(feature); } return success; } void ShapefileTool::SetEncoding(Encoding encoding) { m_encoding = encoding; SetGDALEncoding(); } ShapefileTool::Encoding ShapefileTool::GetEncoding() const { return m_encoding; }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。