作者: 周勇
|
目前基于MO的开发实例以VB居多,VC实例只有MFC目录下自带一些例子。这里给出了几个常见问题的示例代码,希望对刚接触MO的广大VC二次开发人员有所帮助。 基础的入门教程可以参考下面的网址: http://www.esrichina-bj.cn/library/chinanews/new11/news11-mo.htm 目 录 1.为Shape指定Symbol。 2.生成一个线对象的示例 3.为何我画了对象却没有显示? 4.已经获得part,如何组装成Line? 5.获得线的起点、终点的方法。 6.对所有图层依次执行某个操作的示例代码: 7.利用ValueMapRenderer为同一图层N个多边形着色 8.制作一个点图层(转载) 9.改变图层颜色(转载) 10.Fields不能通过索引号来获取Field,怎么办? 11.判断图层类型是点、线还是面图层。 12.在指定的目录下保存全部图层文件。(转载) 13.如何合并两个图层?(转载) -------------------------------------------------------------------------------- 1.为Shape指定Symbol 演示代码如下: -------------------------------------------------------------------------------- { CMoSymbol sym; if (!sym.CreateDispatch("MapObjects2.Symbol")) return; sym.SetColor(moPurple); sym.SetSymbolType(moLineSymbol); //常量定义请见MapObjects2.h sym.SetStyle(moSolidLine); sym.SetSize(2); m_map.DrawShape(line, sym); m_map.Refresh(); } -------------------------------------------------------------------------------- 2.生成一个线对象的示例 演示代码如下: -------------------------------------------------------------------------------- { CMoLine line; line.CreateDispatch("MapObjects2.Line"); CMoPoints pts; pts.CreateDispatch("MapObjects2.Points"); CMoPoint pt; pt.CreateDispatch("MapObjects2.Point"); pt.SetX(1); pt.SetY(1); pts.Add(pt); pt.SetX(100); pt.SetY(100); pts.Add(pt); CMoParts parts(line.GetParts()); parts.Add(pts); } -------------------------------------------------------------------------------- 3.为何我画了对象却没有显示 1,检查图层是否layer.SetVisible(TRUE); 2,检查map的extent是否包含了你所需要显示的对象。关于这个可以参考6中的代码,它通过遍历所有图层,获得了一个最合适的Extent 3,检查该对象是否被其他对象覆盖。 4,检查该对象是的颜色是否与背景相同。 4.已经获得part,如何组装成Line: 演示代码如下: -------------------------------------------------------------------------------- int DEF_P0017(CMoLine* pline) { CMoParts parts = pline->GetParts(); //get parts for(short i=0; i< parts.GetCount(); i++){ CMoPoints P1( parts.Item(COleVariant(i))); //parts-->points CMoLine Line; //create line object if (!Line.CreateDispatch(TEXT("MapObjects2.Line"))){ return 1; }//end if CMoParts ps(Line.GetParts()); //get line's parts ps.Add(P1); //add pline --> parts -->points-->Line }//end for return 0; } -------------------------------------------------------------------------------- 5.获得线的起点(从某种意义上将,也是终点)的方法。 Here's some sample code that assumes that there is at least two points in the line: 演示代码如下: -------------------------------------------------------------------------------- /*** START CODE ***/ //track the line CMoLine myLine(TrackLine()); //get the MoParts of the line. CMoParts myParts(myLine.GetParts()); //get the vertice points. CMoPoints myPoints(myParts.Item(COleVariant((short)0))); //get the number of vertices. long num = myPoints.GetCount(); if (num > 1) { //get the first point. CMoPoint ptFirst( myPoints.Item(COleVariant((short)0))); //get the last point of the line. CMoPoint ptLast(myPoints.Item(COleVariant((short)num-1))); } /*** END CODE **/ -------------------------------------------------------------------------------- 6.对所有图层依次执行某个操作的示例代码: 使用循环可以遍历各个图层,但是你必须匹配图层的title后放可知道该图层是你所需要的图层 此代码还演示了如何使用技巧获得所有图层的最适合的Extent。 -------------------------------------------------------------------------------- double dLimit_Bottom,dLimit_top,dLimit_left,dLimit_right; dLimit_Bottom = dLimit_top = dLimit_left = dLimit_right =0; CMoLayers layers(m_map.GetLayers()); for(short i=0; i < layers.GetCount(); i++) //对所有图层 { CMoMapLayer layer(layers.Item(COleVariant(i) )); if (! layer.GetLayerType()==moMapLayer ){ MessageBox( _T("图层必须是Shape图层,你设置的不是。对不起,无法载入。"), _T("提示"), MB_OK|MB_ICONWARNING); return ; } //设置Extent CMoRectangle RectExtent (layer.GetExtent()); if (RectExtent.GetBottom() < dLimit_Bottom) dLimit_Bottom =RectExtent.GetBottom(); if (RectExtent.GetTop() > dLimit_top) dLimit_top =RectExtent.GetTop(); if (RectExtent.GetLeft() < dLimit_left) dLimit_left =RectExtent.GetLeft(); if (RectExtent.GetRight() > dLimit_right) dLimit_right =RectExtent.GetRight(); //如果是指定的图层,则 if ( "YourShapeTitle" == layer.GetName()){ //do something like follow code: if (moShapeTypeLine!= layer.GetShapeType()){ MessageBox( _T("图层必须是线图层"), _T("提示"), MB_OK|MB_ICONWARNING); return ; }//end if (moShapeTypeLine!= layer.GetShapeType()) }// end if ( "YourShapeTitle" == layer.GetName()) }// end for(short i=0; i < layers.GetCount(); i++) extent.SetBottom (dLimit_Bottom ); extent.SetTop(dLimit_top); extent.SetLeft(dLimit_left); extent.SetRight(dLimit_right); extent.ScaleRectangle(1.2); m_map.SetFullExtent (extent); m_map.SetExtent(extent); -------------------------------------------------------------------------------- 7.利用CMoValueMapRenderer为同一图层N个多边形着色: 演示代码如下: (代码9中转载了另外一种方法,可以指定颜色而不是随机颜色。请见9改变图层颜色) -------------------------------------------------------------------------------- short i = 0; CMoMapLayer layer(layers.Item(COleVariant(i) )); //将每个polygon取出,并为每个多边形着色。 CMoRecordset recs(layer.GetRecords()); // used to hold all polygons CMoStrings strings; VERIFY(strings.CreateDispatch(TEXT("MapObjects2.Strings"))); CMoFields fields(recs.GetFields()); while (!recs.GetEof()) { CMoField Density(fields.Item(COleVariant("Density"))); //这里Density 是一个属性,你可以替代成你自己定义的属性 strings.Add(Density.GetValueAsString()); recs.MoveNext(); } //end while (!recs.GetEof()) //如果多于1个polygon,则为每个多边形着色 if( recs.GetCount() > 1){ // // Set up value map renderer // CMoValueMapRenderer vmRenderer; VERIFY(vmRenderer.CreateDispatch(TEXT("MapObjects2.ValueMapRenderer"))); vmRenderer.SetField(TEXT("Density")); vmRenderer.SetValueCount(strings.GetCount()); for (short i = 0; i < strings.GetCount(); i++) vmRenderer.SetValue(i, strings.Item(COleVariant(i))); layer.SetRenderer(vmRenderer); //着色完毕 } //end if( recs.GetCount() > 1) -------------------------------------------------------------------------------- 8.制作一个点图层(转载): (来自CSDN)有些时候将一些固定的数据制作成图层,可以提高程序的速度,而且使用方便。下面我就将对图层的制作方法进行一下简单的说明。 假设我们要将一些经纬度坐标用点的方式画在地图上,那么我们首先要有保存经纬度坐标的数组:m_LonArray, m_LatArray,均为CArray<float,float>型。然后我们在CMyView中增加一些成员变量: CmoDataConnectionpMoCon; CMoTableDescdesc; CMoMapLayerlayer; CMoPointm_point; 好了,是为创建新图层增加一个函数的时候了,在视图类中增加函数:CreateNewLayer()。 演示代码如下: -------------------------------------------------------------------------------- BOOL CMyView:: CreateNewLayer () { if (!pMoCon.CreateDispatch(TEXT("MapObjects2.DataConnection"))) return FALSE; if(!desc.CreateDispatch("MapObjects2.TableDesc")) return FALSE; VARIANT vt; vt.vt = VT_BOOL; vt.boolVal = VARIANT_FALSE; pMoCon.SetDatabase((LPCTSTR)"E://Demo//经纬度层"); //设置图层保存目录 if(!pMoCon.Connect()) return FALSE; //设置图层的字段个数及属性,这里设置两个,一个为Number,一个为Name。表示点的号码及名称。 desc.SetFieldCount(2); desc.SetFieldType(0,moString); desc.SetFieldName(0,"Number"); desc.SetFieldLength(0,10); desc.SetFieldType(1,moString); desc.SetFieldName(1, "Name"); desc.SetFieldLength(1, 10); //创建新图层,设置名称、类型及字段。 CmoGeoDataSet geoDataset(pMoCon.AddGeoDataset(“经纬度层”, moShapeTypePoint, (LPDISPATCH)desc, vt, vt); if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer"))) return FALSE; //设置图层的记录集 layer.SetGeoDataset(geoDataset); CMoRecordset recs(layer.GetRecords()); CMoFields fields(recs.GetFields()); for(int i=0; i< m_LonArray.GetSize(); i++) { recs.AddNew(); m_point.SetX(m_ LonArray.GetAt(i)); m_point.SetY(m_ LatArray.GetAt(i)); SetValue(fields, "Shape",m_point); SetValue(fields, "Number",m_Number.GetAt(i));//需定义CStringArray m_Number SetValue(fields, "Name", m_Chname.GetAt(i));//需定义CStrignArray m_Name recs.Update(); } //设置点的颜色,并加入地图。 layer.GetSymbol().SetColor(moLightYellow); CMoLayers layers(m_map.GetLayers()); layers.Add(layer); return TRUE; } -------------------------------------------------------------------------------- 好了,调用一下试试效果吧。 9.改变图层颜色(转载) 另外一个简单的随机颜色填充在示例7,请参考7。原作者:张松伟 zswking@163.com 如果你的地国正在显示一个“中国地图”的图层,而图层中每个省的颜色都是一样的,你是不是想把它做成真实地图一样的效果,给各个省填上颜色呢?好,让我们开始吧。 注意,一定要确保你的“中图地图”图层数据中有标识各个省的数据和字段(可以在ArcMap中看到),因为只有能区别出各个区域才能对区域填色,现在我们假设图层名称为China, 标识各个省的字段为NAME。好了,在你程序中加入改变颜色的函数吧。 演示代码如下: -------------------------------------------------------------------------------- void CMapCortrol::ChangeChinaColor() { CMoRecordset recs; //图层的记录集 CMoStrings strs; //MO的字符串类 strs.CreateDispatch("MapObjects2.Strings"); //得到图层数据中NAME字段的第条记录,保存在strs中。 CMoMapLayer lay = m_map.GetLayers().Item(COleVariant("China")); recs = lay.GetRecords(); while(!recs.GetEof()) { CMoFields mfs = recs.GetFields(); CMoField mf = mfs.Item(COleVariant("NAME")); CString s = mf.Get_Value().bstrVal; strs.Add(s); recs.MoveNext(); } //改变区域颜色 CMoValueMapRenderer vmRend; vmRend.CreateDispatch("MapObjects2.ValueMapRenderer"); vmRend.SetValueCount(strs.GetCount()); vmRend.SetField("NAME"); for(int i=0; i< strs.GetCount(); i++) { //将保存的省名附给vmRend VARIANT V; V.vt = VT_I2; V.iVal = i; vmRend.SetValue(i, strs.Item(V)); //取出省名并进行判断 if(vmRend.GetValue(i) == "北京市" || vmRend.GetValue(i) == "上海市" || vmRend.GetValue(i) == "江西省" || vmRend.GetValue(i) == "四川省") { vmRend.GetSymbol(i).SetColor(RGB(239,252,230)); } else if(vmRend.GetValue(i) == "安徽省" || vmRend.GetValue(i) == "黑龙江" || vmRend.GetValue(i) == "辽宁省" || vmRend.GetValue(i) == "广西壮族自治区" || vmRend.GetValue(i) == "台湾省" || vmRend.GetValue(i) == "甘肃省" || vmRend.GetValue(i) == "天津市" || vmRend.GetValue(i) == "山西省") { vmRend.GetSymbol(i).SetColor(RGB(241,232,252)); } else if(vmRend.GetValue(i) == "山东省" || vmRend.GetValue(i) == "陕西省" || vmRend.GetValue(i) == "湖南省" || vmRend.GetValue(i) == "海南省" || vmRend.GetValue(i) == "澳门" || vmRend.GetValue(i) == "香港") { vmRend.GetSymbol(i).SetColor(RGB(252,237,248)); } else if(vmRend.GetValue(i) == "河南省" || vmRend.GetValue(i) == "内蒙古自治区" || vmRend.GetValue(i) == "福建省" || vmRend.GetValue(i) == "贵州省" || vmRend.GetValue(i) == "青海省") { vmRend.GetSymbol(i).SetColor(RGB(252,251,235)); } else if(vmRend.GetValue(i) == "江苏省" || vmRend.GetValue(i) == "西藏自治区") { vmRend.GetSymbol(i).SetColor(RGB(252,230,246)); } else if(vmRend.GetValue(i) == "吉林省" || vmRend.GetValue(i) == "河北省" || vmRend.GetValue(i) == "浙江省" || vmRend.GetValue(i) == "湖北省" || vmRend.GetValue(i) == "广东省" || vmRend.GetValue(i) == "新疆维吾尔族自治区" || vmRend.GetValue(i) == "云南省" || vmRend.GetValue(i) == "宁夏回族自治区") { vmRend.GetSymbol(i).SetColor(RGB(245,252,252)); } //设置省界的颜色 vmRend.GetSymbol(i).SetOutlineColor(RGB(185,185,185)); } lay.SetRenderer(vmRend); m_map.Refresh(); } -------------------------------------------------------------------------------- 10.Fields不能通过索引号来获取Field,怎么办? mo中Fields不能通过索引号来获取Field,只提供了通过字段名称来获取字段的方法,代码如下 -------------------------------------------------------------------------------- short i = 0; CMoMapLayer layer(layers.Item(COleVariant(i) )); CMoRecordset recs(layer.GetRecords()); // used to hold all shapes CMoFields Fields(recs.GetFields()); while (!recs.GetEof()) { CMoFieldShapeField(Fields.Item(COleVariant(TEXT("Shape")))); //指定字段名 //加入你的代码 recs.MoveNext(); } //end while (!recs.GetEof()) -------------------------------------------------------------------------------- 有两种方法可以解决此问题: 一是通过TableDesc来获取Recordset的结构,但是只能获取到属性字段,空间字段无法获取(应该是Shape/FeatureID两个字段获取不到,其他都可以), 详见CMoTableDesc类的GetFieldName()方法。代码如下 -------------------------------------------------------------------------------- CMoDataConnection conn, CMoTableDesc tableDesc CMoGeoDataset geoDataset(conn.AddGeoDataset(GetFileTitle(m_path), moLine, tableDesc, va ,va)); ASSERT(LPDISPATCH(geoDataset)); CString strFieldName; for (i=0;i< tableDesc.GetFieldCount; i++) strFieldName = tableDesc.GetFieldName; -------------------------------------------------------------------------------- 另外也可以用CMoIterator这个类。一般的,对于collection的对象都可以用CMoIterator这个类。示例代码如下: -------------------------------------------------------------------------------- short j = 0; CMoMapLayer layer(layers.Item(COleVariant(j) )); CMoRecordset recs(layer.GetRecords()); // used to hold all shapes CMoFields fields(recs.GetFields()); int iCount=fields.GetCount(); CMoIterator moIterator(fields); CMoField field; moIterator.Reset(); for(int i=0;i< iCount;i++) { moIterator.Next(field); TRACE("name=%s/n",field.GetName()); } -------------------------------------------------------------------------------- 11.判断图层类型是点、线还是面图层。 对一个layer对象使用GetShapeType而不是GetLayerType函数。GetLayerType函数用于判断一个图层是矢量还是栅格的。演示代码如下: -------------------------------------------------------------------------------- CMoLayers layers(m_map.GetLayers()); if (! layer.GetLayerType()==moMapLayer ){ //常量moMapLayer表示矢量图,moImageLayer表示Image图 MessageBox( _T("图层必须是Shape图层,你设置的不是。对不起,无法载入。"), _T("提示"), MB_OK|MB_ICONWARNING); return FALSE; } for(short i=0;i< layers.GetCount();i++) //对所有图层 { CMoMapLayer layer(layers.Item(COleVariant(i) )); if (moShapeTypeLine != layer.GetShapeType())//如果不是线,常量moShapeTypeLine等定义见MapObject2.h { //add your code here! }//end if (moShapeTypeLine != layer.GetShapeType()) }//end for(short i=0;i< layers.GetCount();i++) -------------------------------------------------------------------------------- 12.在指定的目录下保存全部图层文件。 在szPath指定的目录下保存全部图层。演示代码如下: -------------------------------------------------------------------------------- void CMoCov2ShpView::SaveAsShp(CString szPath) { CMoRecordset rst; CMoGeoDataset dst; CMoMapLayer ly; try { rst.CreateDispatch(_T("MapObject2.Recordset")); ly.CreateDispatch(_T("MapObject2.MapLayer")); } catch(COleException *ep) { ep->ReportError(); return; } CString szFileName; CMoLayers lys(m_objMap.GetLayers()); int ilyCounts; ilyCounts = lys.GetCount(); for(int i = 0;i < ilyCounts;i ++) { try { ly = lys.Item(COleVariant((short)i)); szFileName = ly.GetName(); if(szFileName.IsEmpty() != NULL) { szFileName.Format("AutoFileName%d",i); } szFileName = szPath + "//" + szFileName + ".shp"; rst = ly.GetRecords(); rst.Export(szFileName,ly.GetCoordinateSystem()); } catch(COleException *ep) { ep->ReportError(); } }//end for(int i = 0;i < ilyCounts;i ++) } -------------------------------------------------------------------------------- 13.如何合并两个图层? 下面是图层合并的演示代码: -------------------------------------------------------------------------------- void CMoAddShapeView::MergeLayers() { CMoTableDesc oTDesc; CMoGeoDataset oDataset; CMoDataConnection oConnection; CMoRecordset oRecset; CMoMapLayer oLayer,oTempLayer; CMoRecordset oTempRecs; CMoField oField; CMoFields oFields; CMoFields oTempFields; CString szMergeFile; long lshpType; CString szPath; char chPath[MAX_PATH]; int ilen = 0; int fCounts; CString szFName; CMoLayers oLayers(m_objMap.GetLayers()); if( oLayers.GetCount() < 2) //小于2个图层无法合并 return; oTempLayer = oLayers.Item(COleVariant((short)(oLayers.GetCount() -1))); oRecset = oTempLayer.GetRecords(); lshpType = oTempLayer.GetShapeType(); if(m_strMergeFile.IsEmpty() != NULL) { szMergeFile = oTempLayer.GetName(); } else { szMergeFile = m_strMergeFile; } if(!oConnection.CreateDispatch(TEXT("MapObjects2.DataConnection"))) return; if(!oLayer.CreateDispatch(TEXT("MapObjects2.MapLayer"))) return; GetCurrentDirectory(MAX_PATH,chPath); ilen = strlen(chPath); chPath[ilen] = '/0'; szPath = chPath;//[ilen]; oConnection.SetDatabase(szPath); if(oConnection.Connect()) { VARIANT va; VariantInit(&va); va.vt =VT_BOOL; va.bVal = false; oTDesc = oRecset.GetTableDesc(); //oDataset = oConnection.AddGeoDataset("Merged",lshpType,oTDesc,va,va); if(szMergeFile.IsEmpty() != NULL) { CTime tm(CTime::GetCurrentTime()); szMergeFile = "Merged" + tm.Format("%H%M%S"); } oDataset = oConnection.AddGeoDataset(szMergeFile,lshpType,oTDesc,va,va); if(oDataset == NULL) return; oLayer.SetGeoDataset(oDataset); oTempRecs = oLayer.GetRecords(); oTempRecs.SetAutoFlush(FALSE); for(int i= oLayers.GetCount() -1;i >= 0;i --) { oTempLayer = oLayers.Item(COleVariant((short)i)); oRecset = oTempLayer.GetRecords(); if(lshpType != oTempLayer.GetShapeType()) continue; if(!TableDescMatch(oTDesc,oRecset.GetTableDesc())) continue; oRecset.MoveFirst(); while(!oRecset.GetEof()) { oTempRecs.AddNew(); fCounts = oTDesc.GetFieldCount(); VARIANT v; for(short j = 0;j < fCounts;j++) { szFName = oTDesc.GetFieldName(j); OutputDebugString(szFName + "/n/r"); if(szFName.CompareNoCase("Shape") == NULL) { VariantInit(&v); v = oRecset.GetFields().Item(COleVariant(TEXT(szFName))).Getvalue(); LPDISPATCH value; v.vt = VT_DISPATCH; value = v.pdispVal; Setvalue(oTempRecs.GetFields(),szFName,value); } else { oTempRecs.GetFields().Item(COleVariant(TEXT(szFName))).Setvalue(oRecset.GetFields().Item(COleVariant(TEXT(szFName))).Getvalue()); }//end if(szFName.CompareNoCase("Shape") == NULL) }//end for(short j = 0;j < fCounts;j++) VariantInit(&v); v = oRecset.GetFields().Item(COleVariant(TEXT("shape"))).Getvalue(); LPDISPATCH value; v.vt = VT_DISPATCH; value = v.pdispVal; Setvalue(oTempRecs.GetFields(),"Shape",value); Setvalue(oTempRecs.GetFields(),"FeatureID",oRecset.GetFields().Item(COleVariant(TEXT("FeatureID"))).Getvalue()); oTempRecs.Update(); oRecset.MoveNext(); }//while(!oRecset.GetEof()) } //end for(int i= oLayers.GetCount() -1;i >= 0;i --) oTempRecs.SetAutoFlush(TRUE); }// end if(oConnection.Connect()) oLayers.Clear(); oLayers.Add(oLayer); m_objMap.Refresh(); } |
MO2.2 + VC 经验小结
最新推荐文章于 2024-04-22 16:57:34 发布