GDAL线面互转换(2)
在上一个文章中介绍了线转化为面和面转化为线,其主要的实现思路就是把面中的点取出来构成线,把线中的点取出来构成面,实际上就是一个硬拷贝,无奈客户的实际需求并非如此,客户想要线转面的时候几条相交线构成面,面转线的时候相同的线去除,所以又重新对功能进行了调整。
关于线构面,这个过程中也是挺曲折的,在GDAL的群里问了好久,大家给的答案一致是需要自己写,线构面的算法需要使用左转或者右转算法,并且在网上查了相关的资料,发现蒋波涛编著的《插件式GIS应用框架的设计与实现:基于C#和AE 9.2》一书中有ArcGIS实现GDAL的完整代码,没办法,埋头去干吧,先做了一部分前期的验证,验证的时候,公司一大牛问我OGRGeometry中的Polygonize ()方法是干啥的?仔细查阅相关资料,就是要做线转面的啊!赶紧验证,发现失败,后来又仔细分析,似乎该方法需要OGRGeometry的空间拓扑关系正确,如何保证这点儿呢?考虑用Union来把一根根线合并了拓扑关系应该没有问题吧,实际测试了一下,的确正确,心中窃喜。后来拿实际的省界线来合成省面,发现效率超级慢,跟踪代码发现,OGRGeometry合并的时候随着合并线段的增加时间也在快速的增加……问题找到,上网查找解决方案,看到两篇文章(http://www.docin.com/p-1155026547.html)(http://www.docin.com/p-1238395230.html)介绍说可以考虑使用UnionCascaded(级联求并)可以大大的加快效率,实际验证确不知道怎么使用,考虑到项目的进度要求,这个问题暂且搁置了,后续再提高吧。
对于面构线,就相对简单了不少,先把一个个的面转化成线(硬拷贝,参考上一博文中的方法),再把转化成的线Union了,生成一个拓扑关系正确的OGRMultiPolygon,再调用Simplify方法,得到的结果即为想要的线,不过当线特别多还很复杂的时候效率也高,问题和线构面的时候一样。
在此补充上源代码,在此留个记录,后续考虑怎么解决这个问题吧……
/*
* @brief ConvertPolygonToPolyline 面图层转换为线图层
* @param[in] tString polylinePath 转换后线图层文件路径
* @param[in] OGRLayer* pLayer 要转换的面图层文件
* @param[in] Envelope envelope 要转换数据的范围
* @param[in] vector<long> vecFIDs 选中的要素ID列表
* @param[in] pOGRSpatialReference 要转换的数据的空间参考(如果为空表示坐标系信息不变)
* @return bool 是否成功
* @author
* @date
* @note 2015年11月04日 小八创建;
*/
bool FeatureLayerOperator::ConvertPolygonToPolylineEx(tString polylinePath,OGRLayer* pLayer,Envelope envelope,vector<long> vecFIDs,OGRSpatialReference* pOGRSpatialReference)
{
// 判断
if(pLayer==NULL) return false;
if(true==polylinePath.empty()) return false; // 坐标系读取
OGRSpatialReference* pOGRSpatialReference_Source=pLayer->GetSpatialRef();
bool isSameCoordSystem = false;
if(pOGRSpatialReference == NULL)
{
pOGRSpatialReference=pOGRSpatialReference_Source;
isSameCoordSystem=true;
}
else if(pOGRSpatialReference!=NULL && pOGRSpatialReference_Source!=NULL)
{
isSameCoordSystem=pOGRSpatialReference_Source->IsSame(pOGRSpatialReference);
} // 创建Shape文件
OGRDataSource* pOGRDataSource=CreateShapeFile(polylinePath,pOGRSpatialReference,wkbLineString);
if(pOGRDataSource==NULL) return false; OGRLayer* pOGRLayer=pOGRDataSource->GetLayer();
if(pOGRLayer==NULL) return false; // 面转线再合并
OGRFeature* pOGRFeature_Old;
OGRGeometry* pTempGeometry=NULL;
OGRGeometry* pTempGeometryUnion=NULL; // 当前选择导出
if(false==vecFIDs.empty()&&vecFIDs.size()>)
{
for(int i=;i<vecFIDs.size();i++)
{
pOGRFeature_Old=pLayer->GetFeature(vecFIDs[i]);
pTempGeometry=ConvertPolygonToPolylineGeo(pOGRFeature_Old->GetGeometryRef());
pTempGeometry->assignSpatialReference(pOGRSpatialReference_Source);
if(false == isSameCoordSystem)pTempGeometry->transformTo(pOGRSpatialReference); if(pTempGeometryUnion==NULL) pTempGeometryUnion=pTempGeometry;
else pTempGeometryUnion=pTempGeometryUnion->Union(pTempGeometry);
}
}
else
{
if(false!=envelope.isNull()&&envelope.getMaxX()!=envelope.getMinX())
{
pLayer->SetSpatialFilterRect(envelope.getMinX(),envelope.getMinY(),envelope.getMaxX(),envelope.getMaxY());
} pOGRFeature_Old=pLayer->GetNextFeature();
while(NULL!= pOGRFeature_Old)
{
pTempGeometry=ConvertPolygonToPolylineGeo(pOGRFeature_Old->GetGeometryRef());
pTempGeometry->assignSpatialReference(pOGRSpatialReference_Source);
if(false == isSameCoordSystem)pTempGeometry->transformTo(pOGRSpatialReference); if(pTempGeometryUnion==NULL) pTempGeometryUnion=pTempGeometry;
else pTempGeometryUnion=pTempGeometryUnion->Union(pTempGeometry); pOGRFeature_Old=pLayer->GetNextFeature();
}
} // 获得Simply的距离
double distanceValue=0.0;
if(NULL==pOGRSpatialReference) // 如果为空
{
OGREnvelope pTempOGREnvelope ;
pTempGeometryUnion->getEnvelope(&pTempOGREnvelope);
if(pTempOGREnvelope.MaxX<) distanceValue=0.00000001;
else distanceValue=0.01;
}
else if(true==pOGRSpatialReference->IsProjected()) // 如果是Project的
{
distanceValue=0.01;
}
else // 如果是Geo的
{
distanceValue=0.00000001;
}
pTempGeometryUnion=pTempGeometryUnion->Simplify(distanceValue); // 在ShapeFile文件中添加数据行
OGRFeature* pOGRFeature_New;
OGRGeometry* pOGRGeometry;
OGRFeatureDefn* pOGRFeatureDefn=NULL;
pOGRFeatureDefn=pOGRLayer->GetLayerDefn(); OGRwkbGeometryType ogrGeometryType=pTempGeometryUnion->getGeometryType();
ogrGeometryType=wkbFlatten(ogrGeometryType); if(ogrGeometryType==OGRwkbGeometryType::wkbMultiLineString)
{
OGRGeometryCollection* pOGRGeometryCollectionTarget=(OGRGeometryCollection*) pTempGeometryUnion;
int geometryCount=pOGRGeometryCollectionTarget->getNumGeometries();
for(int i=;i<geometryCount;i++)
{
pOGRFeature_New=OGRFeature::CreateFeature(pOGRFeatureDefn);
pOGRGeometry=pOGRGeometryCollectionTarget->getGeometryRef(i);
pOGRFeature_New->SetGeometry(pOGRGeometry);
pOGRLayer->CreateFeature(pOGRFeature_New); OGRFeature::DestroyFeature(pOGRFeature_New);
pOGRFeature_New=NULL;
}
}
else if(ogrGeometryType==OGRwkbGeometryType::wkbLineString)
{
pOGRFeature_New=OGRFeature::CreateFeature(pOGRFeatureDefn);
pOGRGeometry=pTempGeometryUnion;
pOGRFeature_New->SetGeometry(pOGRGeometry);
pOGRLayer->CreateFeature(pOGRFeature_New); OGRFeature::DestroyFeature(pOGRFeature_New);
pOGRFeature_New=NULL; }
OGRDataSource::DestroyDataSource(pOGRDataSource); // 销毁pTargetGeometrys
OGRGeometryFactory::destroyGeometry(pTempGeometryUnion);
pTempGeometryUnion=NULL; return true;
} /*
* @brief ConvertPolygonToPolyline 线图层转换为面图层
* @param[in] tString polylinePath 转换后面图层文件路径
* @param[in] OGRLayer* pLayer 要转换的线图层文件
* @param[in] Envelope envelope 要转换数据的范围
* @param[in] vector<long> vecFIDs 选中的要素ID列表
* @param[in] pOGRSpatialReference 要转换的数据的空间参考(如果为空表示坐标系信息不变)
* @return bool 是否成功
* @author
* @date
* @note 2015年11月04日 小八创建;
*/
bool FeatureLayerOperator::ConvertPolylineToPolygonEx(tString polylinePath,OGRLayer* pLayer,Envelope envelope,vector<long> vecFIDs,OGRSpatialReference* pOGRSpatialReference)
{
// 判断
if(pLayer==NULL) return false;
if(true==polylinePath.empty()) return false; // 坐标系读取
OGRSpatialReference* pOGRSpatialReference_Source=pLayer->GetSpatialRef();
bool isSameCoordSystem = false;
if(pOGRSpatialReference == NULL)
{
pOGRSpatialReference=pOGRSpatialReference_Source;
isSameCoordSystem=true;
}
else if(pOGRSpatialReference!=NULL && pOGRSpatialReference_Source!=NULL)
{
isSameCoordSystem=pOGRSpatialReference_Source->IsSame(pOGRSpatialReference);
} // 创建Shape文件
OGRDataSource* pOGRDataSource=CreateShapeFile(polylinePath,pOGRSpatialReference,wkbPolygon);
if(pOGRDataSource==NULL) return false; OGRLayer* pOGRLayer=pOGRDataSource->GetLayer();
if(pOGRLayer==NULL) return false; // 面合并
OGRFeature* pOGRFeature_Old;
OGRGeometry* pTempGeometry=NULL;
OGRGeometry* pTempGeometryUnion=NULL; // 当前选择导出
if(false==vecFIDs.empty()&&vecFIDs.size()>)
{
for(int i=;i<vecFIDs.size();i++)
{
pOGRFeature_Old=pLayer->GetFeature(vecFIDs[i]);
pTempGeometry=pOGRFeature_Old->GetGeometryRef();
if(false == isSameCoordSystem)pTempGeometry->transformTo(pOGRSpatialReference); if(pTempGeometryUnion==NULL) pTempGeometryUnion=pTempGeometry;
else pTempGeometryUnion=pTempGeometryUnion->Union(pTempGeometry);
}
}
else
{
if(false!=envelope.isNull()&&envelope.getMaxX()!=envelope.getMinX())
{
pLayer->SetSpatialFilterRect(envelope.getMinX(),envelope.getMinY(),envelope.getMaxX(),envelope.getMaxY());
} pOGRFeature_Old=pLayer->GetNextFeature();
while(NULL!= pOGRFeature_Old)
{
pTempGeometry=pOGRFeature_Old->GetGeometryRef();
if(false == isSameCoordSystem)pTempGeometry->transformTo(pOGRSpatialReference); if(pTempGeometryUnion==NULL) pTempGeometryUnion=pTempGeometry;
else pTempGeometryUnion=pTempGeometryUnion->Union(pTempGeometry); pOGRFeature_Old=pLayer->GetNextFeature();
}
} OGRGeometry* pOGRGeometryUnion = pTempGeometryUnion->Polygonize(); // 在ShapeFile文件中添加数据行
OGRFeature* pOGRFeature_New;
OGRGeometry* pOGRGeometry;
OGRFeatureDefn* pOGRFeatureDefn=NULL;
pOGRFeatureDefn=pOGRLayer->GetLayerDefn(); OGRwkbGeometryType ogrGeometryType=pOGRGeometryUnion->getGeometryType();
ogrGeometryType=wkbFlatten(ogrGeometryType); if(ogrGeometryType==OGRwkbGeometryType::wkbGeometryCollection||ogrGeometryType==OGRwkbGeometryType::wkbMultiPolygon)
{
OGRGeometryCollection* pOGRGeometryCollectionTarget=(OGRGeometryCollection*) pOGRGeometryUnion;
int geometryCount=pOGRGeometryCollectionTarget->getNumGeometries();
for(int i=;i<geometryCount;i++)
{
pOGRFeature_New=OGRFeature::CreateFeature(pOGRFeatureDefn);
pOGRGeometry=pOGRGeometryCollectionTarget->getGeometryRef(i);
pOGRFeature_New->SetGeometry(pOGRGeometry);
pOGRLayer->CreateFeature(pOGRFeature_New); OGRFeature::DestroyFeature(pOGRFeature_New);
pOGRFeature_New=NULL;
}
}
else if(ogrGeometryType==OGRwkbGeometryType::wkbPolygon)
{
pOGRFeature_New=OGRFeature::CreateFeature(pOGRFeatureDefn);
pOGRGeometry=pOGRGeometryUnion;
pOGRFeature_New->SetGeometry(pOGRGeometry);
pOGRLayer->CreateFeature(pOGRFeature_New); OGRFeature::DestroyFeature(pOGRFeature_New);
pOGRFeature_New=NULL; }
OGRDataSource::DestroyDataSource(pOGRDataSource); // 销毁pTargetGeometrys
OGRGeometryFactory::destroyGeometry(pTempGeometryUnion);
pTempGeometryUnion=NULL; return true;
}
GDAL线面互转换(2)的更多相关文章
- GDAL线面互转换
最近因为项目需要,需做GDAL线面互转的功能,查阅部分资料完成,下面把核心部分的代码贴出来,留个记录,也欢迎大家提问题指正完善. /* * @brief ConvertPolygonToPolylin ...
- opengl中场景变换|2D与3D互转换(转)
opengl中场景变换|2D与3D互转换 我们生活在一个三维的世界——如果要观察一个物体,我们可以: 1.从不同的位置去观察它.(视图变换) 2.移动或者旋转它,当然了,如果它只是计算机里面的物体,我 ...
- PHP时间戳和日期互转换
在php中我们要把时间戳转换日期可以直接使用date函数来实现,如果要把日期转换成时间戳可以使用strtotime()函数实现,下面我来给大家举例说明. 1.php中时间转换函数 strtotime ...
- Javascript Array和String的互转换。
Array类可以如下定义: var aValues = new Array(); 如果预先知道数组的长度,可以用参数传递长度 var aValues = new Array(20); -------- ...
- Javascript Array和String的互转换
Array类可以如下定义: var aValues = new Array(); 如果预先知道数组的长度,可以用参数传递长度 var aValues = new Array(20); -------- ...
- C#二进制与字符串互转换,十六进制转换为字符串、float、int
/// <summary> /// 将 字符串 转成 二进制 “10011100000000011100011111111101” /// </summary> /// ...
- Image与Base64String的互转换
public Image Base64ToImage(string base64String) { // Convert Base64 String to byte[] byte[] imageByt ...
- Gdal 1.11.0 添加 Postgresql 9.1 sqlite3 支持
OS环境Ubuntu12.04 32bit 因为公司一个功能要用到gdal 的ogr2ogr命令转换shp数据,需要能往postgis和sqlite 中插入数据. 用gdal1.11.0的源码默认安装 ...
- c#中将IP地址转换成无符号整形数的方法与逆变换方法
我们知道 IP地址就是给每个连接在Internet上的主机分配的一个32bit地址. 按照TCP/IP协议规定,IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节.而c#中 ...
随机推荐
- centos7启动顺序加密的问题
在上一篇博客中我们说的是如何进入单用户模式,这篇我主要来讲centos7启动加密. 首先我们来说centos的启动顺序: 上一篇我们所说的进入单用户模式,就是在boot loader 这一层次下进入的 ...
- docker微服务部署之:六、Rancher管理部署微服务
docker微服务部署之:五.利用DockerMaven插件自动构建镜像 一. 什么是Rancher Rancher是一个开源的企业级容器管理平台.通过Rancher,企业再也不必自己使用一系列的开源 ...
- MySQL多源复制(八)
一.什么是多源复制 MySQL 5.7发布后,在复制方面有了很大的改进和提升.比如开始支持多源复制(multi-source)以及真正的支持多线程复制了.多源复制可以使用基于二进制日志的复制或者基于事 ...
- Oracle PL/SQL学习之基础篇(2)--例外
1.例外分类:系统例外.自定义例外 (1)系统例外,参见相关API文档 (2)自定义例外 定义自己的例外:就像自定义变量一样,类型为exception 抛出例外:使用raise抛出自定义例外 set ...
- Eclipse+jboss5 无法启动
在使用Eclipse luna 配置Jboss5 时,配置成功,但无法在eclipse 控制台上启动. log: Deployment "AttachmentStore" is i ...
- C# 通过IEnumberable接口和IEnumerator接口实现泛型和非泛型自定义集合类型foreach功能
IEnumerator和IEnumerable的作用 其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环,如 ...
- Disconf 学习系列之Disconf是什么?
不多说,直接上干货! Disconf是什么 Distributed Configuration Management Platform(分布式配置管理平台) ,它是专注于各种分布式系统配置管理 的通用 ...
- windows server 2012 如何开启 hyper-v 并创建虚拟机
当我们拿到一台新的windows server 2012 服务器的时候,默认hyper-v是没有开启的,如果我们要在windows server上面创建虚拟机,那么我们也就需要开启hyper-v. 开 ...
- 剑指offer65:矩阵中的路径
题目描述: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵 ...
- hadoop的RPC机制 -源码分析
这些天一直奔波于长沙和武汉之间,忙着腾讯的笔试.面试,以至于对hadoop RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上 ...