mo2.2+vc小結[轉]

目前基於MO的開發實例以VB居多,VC實例只有MFC目錄下自帶一些例子。這裏給出了幾個常見問題的示例代碼,希望對剛接觸MO的廣大VC二次開發人員有所幫助。
--------------------------------------------------------------------------------
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型。然後我們在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。原作者:張松偉 [email protected]
如果你的地國正在顯示一個“中國地圖”的圖層,而圖層中每個省的顏色都是一樣的,你是不是想把它做成真實地圖一樣的效果,給各個省填上顏色呢?好,讓我們開始吧。
注意,一定要確保你的“中圖地圖”圖層數據中有標識各個省的數據和字段(可以在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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章