VC+MO 实现线地图取点坐标
来源:互联网 发布:淘宝的个人主页在哪里 编辑:程序博客网 时间:2024/04/27 17:15
好久没写文章了,可能是懒的缘故.
最近在搞毕设,忙得头晕,之前在Linux下玩得爽,懒得去学VC,这次不幸用到了,着实郁闷.
言归正传,我们的毕设做的是利用一种称为R-tree的数据结构去索引二维平面中的物体.而其索引的依据则是物体的坐标.但是我们所得到的一张
USA加州的公路网图却只有线图层,也就是说,整幅地图中,只有线,却没有点,而要去索引这些路段,我们就必须得到每条路段的起始与终止点坐标
才可以.因此,我必须利用MO去得到每条线段的起始终止点坐标.
如何去取呢.我的方法是取到图中的每一条线,然后去取线的两端点,最后取坐标.看起来比较简单,要做的话就有点麻烦了
首先是MO的安装,我是在天网上搜到MapObjects2的安装包的,下到后安装一下就可以了.下载的地址记不大清了
装好MO后,我们可以在一个MFC工程中添加ActiveX控件加入MO控件.在VC的"工程"->"添加工程"->"Component and controls",然后选择
MapObjects2即可,这时你会发现你的控件工具箱里就会多出一个地图控件MapObjects2.Map来,其对象类型为CMap1
将地图控件拖到Form中去,设置属性,加入地图文件 shp,运行程序,即可在程序中显示地图,跟ArcView一样.
当然,我们的想法是能够动态地去显示地图,而非如此生硬地指定某一地图文件即可.因此,我们的程序就可以这样:
我们采用的MFC是FormView,在MainForm中插入地图控件m_map后,在View类中加入几个私有变量:
CMoDataConnection conn;
CString path;
CMoMapLayer layer;
其中,CMoDataConnection是负责数据连接的,shp文件的打开同数据库类似,必须先做连接,再做记录集等等才可,这点我们以后再讲
path是文件路径,layer是指m_map中的一个图层,用来添加一幅地图
在定义这些变量后,我们在OnInitialUpdate中加入如下语句:
path="map//part2.shp";
//建立数据连接...
conn.CreateDispatch(TEXT("MapObjects2.DataConnection"));
conn.SetDatabase(GetFileDirectory(path));
if(!conn.Connect())
throw new CFileException(CFileException::fileNotFound);
//连接图层...
layer.CreateDispatch(TEXT("MapObjects2.MapLayer"));
CMoLayers layers(m_map.GetLayers());
CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
layer.SetGeoDataset(geoDataset);
//加入图层...
layers.Add(layer);
就如前面所讲的那样,打开shp文件与数据库类似,首先建立连接,然后连接图层,即具体地图,
由语句CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)))所完成,最后,由地图控件的图层集合加入此图层即可
其中,GetFileTitle()等函数都是自定义的,如下所示:
CString CMO_T6View::GetFileDirectory(const CString& path){
ASSERT(path.GetLength());
int pos = path.ReverseFind('//');
if(pos>=0)
return path.Left(pos);
return "";
}
//-----------------------------------------------------------
CString CMO_T6View::GetFileName(const CString& path){
ASSERT(path.GetLength());
int pos=path.ReverseFind('//');
if (pos >=0)
return path.Right(path.GetLength()-pos-1);
return "";
}
//-----------------------------------------------------------
CString CMO_T6View::GetFileTitle(const CString& path){
ASSERT(path.GetLength());
CString strResult= GetFileName(path);
int pos=strResult.ReverseFind('.');
if(pos>=0)
return strResult.Left(pos);
return strResult;
}
设置好图层后,我们就可以动态地加入地图文件,只要设定文件路径即可
全部设置妥当后,接下去就是我们的核心部分,取点.我利用加入菜单项进行操作,程序如下:
//取得数据集...
CMoRecordset recs(layer.GetRecords());
CMoFields fields(recs.GetFields());
CMoField _IDfield(fields.Item(COleVariant( TEXT("OBJECTID") ) ));
//查询用变量...
CMoRecordset searRecs;
CMoFields searFields;
searFields.CreateDispatch(TEXT("MapObjects2.Fields"));
CMoField searField;
searField.CreateDispatch(TEXT("MapObjects2.Field"));
FILE *fp=fopen(GetFileTitle(path),"w");
CString ObjectID;
CString expression,result;
float x,y;
long i=0,j=0;
while(!recs.GetEof()){
//输出数据...
ObjectID=_IDfield.GetValueAsString();
m_list.InsertItem(i,ObjectID);
fromNode=_FNfield.GetValueAsString();
m_list.SetItemText(i,1,fromNode);
toNode=_TNfield.GetValueAsString();
m_list.SetItemText(i,3,toNode);
expression="Objectid=";
expression+=ObjectID;
expression+="";
//取到线段.....取形状类一率用Shape
searRecs=layer.SearchExpression(expression);
searFields=searRecs.GetFields();
searField=searFields.Item(COleVariant(TEXT("Shape")));
CMoLine line;
line.AttachDispatch(searField.GetValue().pdispVal);
CMoParts parts=line.GetParts();
CMoPoints pts;
VARIANT psItem;
psItem.vt=VT_I4;
psItem.lVal=0;
pts.AttachDispatch(parts.Item(psItem));
CMoPoint pt;
VARIANT pItem;
pItem.vt=VT_I4;
for(j=0;j<pts.GetCount();j++){
pItem.lVal=j;
pt=pts.Item(pItem);
x=pt.GetX();
y=pt.GetY();
result.Format("%f %f",x,y);
if(j==0){
fprintf(fp,"%d %f %f",i,x,y);
m_list.SetItemText(i,2,result);
}
else if(j==pts.GetCount()-1){
fprintf(fp," %f %f/n",x,y);
m_list.SetItemText(i,4,result);
i++;
}
else{
fprintf(fp," %f %f/n",x,y);
m_list.SetItemText(i,4,result);
i++;
m_list.InsertItem(i,ObjectID);
fprintf(fp,"%d %f %f",i,x,y);
m_list.SetItemText(i,2,result);
}
}
recs.MoveNext();
}
fclose(fp);
此程序通过查询数据库中的ID字段,取到地图中的每条线段,由于线段可能是折线,因此取到线中的每个点,两个点一对地置入列表控件m_list并
写入文件fp中去.
(以上程序因需要,截去部分,但大部分内容还是保留的)
查询字段值通过以下三句完成:
CMoRecordset recs(layer.GetRecords());
CMoFields fields(recs.GetFields());
CMoField _IDfield(fields.Item(COleVariant( TEXT("OBJECTID") ) ));
先取到记录集recs,根据记录集取到列集合fields,再依据字段名取到具体字段
while(!recs.GetEof()){
ObjectID=_IDfield.GetValueAsString();
...
recs.MoveNext();
}
利用以上语句取出相应字段值.
封装查询语句expression:
expression="Objectid=";
expression+=ObjectID;
expression+="";
通过查询语句取到直线,并赋到相应直线对象中去
searRecs=layer.SearchExpression(expression);
searFields=searRecs.GetFields();
searField=searFields.Item(COleVariant(TEXT("Shape")));
CMoLine line;
line.AttachDispatch(searField.GetValue().pdispVal);
其中,searField=searFields.Item(COleVariant(TEXT("Shape")))做的是通过Shape关键字,取到图形元素
而line通过AttachDispatch取到searField的图形元素对象
取到线段后,通过line->parts->points->point的顺序取点,各类型之间是集合关系,通过Item方法取值,具体可参见代码
东西做了很久,终于算是比较顺利地完成了.对MO和MFC都不熟,之所以能做出来,非常感谢网上好友的支持.
最近在搞毕设,忙得头晕,之前在Linux下玩得爽,懒得去学VC,这次不幸用到了,着实郁闷.
言归正传,我们的毕设做的是利用一种称为R-tree的数据结构去索引二维平面中的物体.而其索引的依据则是物体的坐标.但是我们所得到的一张
USA加州的公路网图却只有线图层,也就是说,整幅地图中,只有线,却没有点,而要去索引这些路段,我们就必须得到每条路段的起始与终止点坐标
才可以.因此,我必须利用MO去得到每条线段的起始终止点坐标.
如何去取呢.我的方法是取到图中的每一条线,然后去取线的两端点,最后取坐标.看起来比较简单,要做的话就有点麻烦了
首先是MO的安装,我是在天网上搜到MapObjects2的安装包的,下到后安装一下就可以了.下载的地址记不大清了
装好MO后,我们可以在一个MFC工程中添加ActiveX控件加入MO控件.在VC的"工程"->"添加工程"->"Component and controls",然后选择
MapObjects2即可,这时你会发现你的控件工具箱里就会多出一个地图控件MapObjects2.Map来,其对象类型为CMap1
将地图控件拖到Form中去,设置属性,加入地图文件 shp,运行程序,即可在程序中显示地图,跟ArcView一样.
当然,我们的想法是能够动态地去显示地图,而非如此生硬地指定某一地图文件即可.因此,我们的程序就可以这样:
我们采用的MFC是FormView,在MainForm中插入地图控件m_map后,在View类中加入几个私有变量:
CMoDataConnection conn;
CString path;
CMoMapLayer layer;
其中,CMoDataConnection是负责数据连接的,shp文件的打开同数据库类似,必须先做连接,再做记录集等等才可,这点我们以后再讲
path是文件路径,layer是指m_map中的一个图层,用来添加一幅地图
在定义这些变量后,我们在OnInitialUpdate中加入如下语句:
path="map//part2.shp";
//建立数据连接...
conn.CreateDispatch(TEXT("MapObjects2.DataConnection"));
conn.SetDatabase(GetFileDirectory(path));
if(!conn.Connect())
throw new CFileException(CFileException::fileNotFound);
//连接图层...
layer.CreateDispatch(TEXT("MapObjects2.MapLayer"));
CMoLayers layers(m_map.GetLayers());
CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
layer.SetGeoDataset(geoDataset);
//加入图层...
layers.Add(layer);
就如前面所讲的那样,打开shp文件与数据库类似,首先建立连接,然后连接图层,即具体地图,
由语句CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)))所完成,最后,由地图控件的图层集合加入此图层即可
其中,GetFileTitle()等函数都是自定义的,如下所示:
CString CMO_T6View::GetFileDirectory(const CString& path){
ASSERT(path.GetLength());
int pos = path.ReverseFind('//');
if(pos>=0)
return path.Left(pos);
return "";
}
//-----------------------------------------------------------
CString CMO_T6View::GetFileName(const CString& path){
ASSERT(path.GetLength());
int pos=path.ReverseFind('//');
if (pos >=0)
return path.Right(path.GetLength()-pos-1);
return "";
}
//-----------------------------------------------------------
CString CMO_T6View::GetFileTitle(const CString& path){
ASSERT(path.GetLength());
CString strResult= GetFileName(path);
int pos=strResult.ReverseFind('.');
if(pos>=0)
return strResult.Left(pos);
return strResult;
}
设置好图层后,我们就可以动态地加入地图文件,只要设定文件路径即可
全部设置妥当后,接下去就是我们的核心部分,取点.我利用加入菜单项进行操作,程序如下:
//取得数据集...
CMoRecordset recs(layer.GetRecords());
CMoFields fields(recs.GetFields());
CMoField _IDfield(fields.Item(COleVariant( TEXT("OBJECTID") ) ));
//查询用变量...
CMoRecordset searRecs;
CMoFields searFields;
searFields.CreateDispatch(TEXT("MapObjects2.Fields"));
CMoField searField;
searField.CreateDispatch(TEXT("MapObjects2.Field"));
FILE *fp=fopen(GetFileTitle(path),"w");
CString ObjectID;
CString expression,result;
float x,y;
long i=0,j=0;
while(!recs.GetEof()){
//输出数据...
ObjectID=_IDfield.GetValueAsString();
m_list.InsertItem(i,ObjectID);
fromNode=_FNfield.GetValueAsString();
m_list.SetItemText(i,1,fromNode);
toNode=_TNfield.GetValueAsString();
m_list.SetItemText(i,3,toNode);
expression="Objectid=";
expression+=ObjectID;
expression+="";
//取到线段.....取形状类一率用Shape
searRecs=layer.SearchExpression(expression);
searFields=searRecs.GetFields();
searField=searFields.Item(COleVariant(TEXT("Shape")));
CMoLine line;
line.AttachDispatch(searField.GetValue().pdispVal);
CMoParts parts=line.GetParts();
CMoPoints pts;
VARIANT psItem;
psItem.vt=VT_I4;
psItem.lVal=0;
pts.AttachDispatch(parts.Item(psItem));
CMoPoint pt;
VARIANT pItem;
pItem.vt=VT_I4;
for(j=0;j<pts.GetCount();j++){
pItem.lVal=j;
pt=pts.Item(pItem);
x=pt.GetX();
y=pt.GetY();
result.Format("%f %f",x,y);
if(j==0){
fprintf(fp,"%d %f %f",i,x,y);
m_list.SetItemText(i,2,result);
}
else if(j==pts.GetCount()-1){
fprintf(fp," %f %f/n",x,y);
m_list.SetItemText(i,4,result);
i++;
}
else{
fprintf(fp," %f %f/n",x,y);
m_list.SetItemText(i,4,result);
i++;
m_list.InsertItem(i,ObjectID);
fprintf(fp,"%d %f %f",i,x,y);
m_list.SetItemText(i,2,result);
}
}
recs.MoveNext();
}
fclose(fp);
此程序通过查询数据库中的ID字段,取到地图中的每条线段,由于线段可能是折线,因此取到线中的每个点,两个点一对地置入列表控件m_list并
写入文件fp中去.
(以上程序因需要,截去部分,但大部分内容还是保留的)
查询字段值通过以下三句完成:
CMoRecordset recs(layer.GetRecords());
CMoFields fields(recs.GetFields());
CMoField _IDfield(fields.Item(COleVariant( TEXT("OBJECTID") ) ));
先取到记录集recs,根据记录集取到列集合fields,再依据字段名取到具体字段
while(!recs.GetEof()){
ObjectID=_IDfield.GetValueAsString();
...
recs.MoveNext();
}
利用以上语句取出相应字段值.
封装查询语句expression:
expression="Objectid=";
expression+=ObjectID;
expression+="";
通过查询语句取到直线,并赋到相应直线对象中去
searRecs=layer.SearchExpression(expression);
searFields=searRecs.GetFields();
searField=searFields.Item(COleVariant(TEXT("Shape")));
CMoLine line;
line.AttachDispatch(searField.GetValue().pdispVal);
其中,searField=searFields.Item(COleVariant(TEXT("Shape")))做的是通过Shape关键字,取到图形元素
而line通过AttachDispatch取到searField的图形元素对象
取到线段后,通过line->parts->points->point的顺序取点,各类型之间是集合关系,通过Item方法取值,具体可参见代码
东西做了很久,终于算是比较顺利地完成了.对MO和MFC都不熟,之所以能做出来,非常感谢网上好友的支持.
- VC+MO 实现线地图取点坐标
- VC+MO实现地图的放大,缩小和漫游
- 百度地图实现固定坐标点定位
- 实现在地图上显示几个坐标点
- 百度地图取点
- chipchunp取碰撞点坐标
- 利用百度地图API实现gps坐标到百度坐标的批量坐标转换(如1000个点)
- VC 获取鼠标点坐标
- VC里使用MO
- VC+MO图形渲染
- 快速查询百度地图坐标点
- D3地图上如何标注坐标点
- 多坐标点地图全部显示
- 坑!百度地图初始化点坐标固定
- 百度地图-设置中性点坐标
- 百度地图中心坐标点如何获取
- MFC设置坐标画曲线取点
- arcgis runtime for iOS100.0 加载地图 按坐标加载点 objective-c实现
- IE弹出窗口打不开
- 上海,什么人穿步鞋
- 使用XML封装数据库操作语句的实现
- Redhat9+Apache2+Mysql4+PHP4+GD2+Perl
- 出货与成本计算
- VC+MO 实现线地图取点坐标
- SQL Server 里查询日期
- 构造使用类C语言的脚本引擎(1)脚本语法定义
- 我不想心就这么冷下去
- Window网络编程之Winsock(一)起步
- 创建成功的工程
- 在C#中使用XML指南之读取XML
- JAVA编程100例
- 把柯达映象搬到Windows XP中