Accessing map objects from your source code

In this article we describe 3 methods of accessing map objects from your source code. Keymap SDK C++ Edition can be integrated into your application in many ways. You may choose to derive your view class from CMUIMap class, or directly use CMUIMap class, or even use CMapT class etc. However, the concept of accessing and manipulating map objects and layers always are the same. In some of your own classes, you have to implement member functions like this:

CMapT* GetMap();

By default, applications generated by Keymap SDK wizards have view class derived from CMUIMap, so GetMap method is available in your view class. Once the pointer to the CMapT object is obtained, the rest is quite simple: using the CMapT member functions for accessing layers, and thus the map objects.

Accessing to specified layer

First you need to get pointer to desired layer.

// get layer using zero-based index)
CMapLayer* pLayer = GetMap()->GetLayer(iLayer);
// get layer by name
CMapLayer* pLayer = GetMap()->FindLayer(strName);
ASSERT(pLayer); //make sure that pLayer not NULL

After layer pointer obtained, use CMapLayer API to access map objects.

Accessing map objects by ID

Object ID is unique integer used for object identification in Keymap database. If you know some object ID, use GetObject method to access this object.

// iID is unique object ID
CMapObject* pObj = pLayer->GetObject(iID);
// do something with pObj
if(pObj->GetType() == polygon) {
   ...
}
// commit object changes
pObj->Commit();
// makes changes permanent in the database if needed
// if you don't want to save changes in layer database, do not call this method
pLayer->Commit();
// free memory to avoid memory leaks
FREE(pObj);

Accessing map objects sequentially

If object ID is unknown, or you need to iterate through all map objects in the layer, use CMapLayer::GetObjectIndex method.

// i is object zero-based index
for(int i=0;i<pLayer->GetObjectCount();i++) {
   CMapObject* pObj = pLayer->GetObjectIndex(i);
   // do something with pObj 
   ...
   //and commit object changes
   pObj->Commit();
   // free memory to avoid memory leaks
   FREE(pObj);
}
// makes changes permanent in the database if needed
// if you don't want to save changes in layer database, do not call this method
pLayer->Commit();

Fastest method of accessing all map objects

This method provide very fast access to map objects, however not in right order (from beginning to end of the layer). Furthermore, you must iterate through nodes and none-node objects separately.

Iterate through all none-node objects

//get first none-node object
CMapObject* pObj = pLayer->GetFirstInXtreeObject(false);//true if you need to load metadata (slower), false if no metadata (faster)
// do something with the object
if(pObj) {
   ... 
   //and commit object changes
   pObj->Commit();
   // free memory to avoid memory leaks
   FREE(pObj);
}
// now can get next object
pObj = pLayer->GetNextInXtreeObject(false);
// if pObj is NULL, you reach the end of the layer
if(pObj) {
   ...
}
// makes changes permanent in the database if needed
// if you don't want to save changes in layer database, do not call this method
pLayer->Commit();

Iterate through all node objects

//get first node object
CMapObject* pObj = pLayer->GetFirstNode(false);//true if you need to load 
metadata (slower), false if no metadata (faster)
// do something with the object
if(pObj) {
   ...
   //and commit object changes
   pObj->Commit();
   // free memory to avoid memory leaks
   FREE(pObj);
}
// now can get next node
pObj = pLayer->GetNextNode(false);
// if pObj is NULL, you reach the end of the layer
if(pObj) {
   ...
}
// makes changes permanent in the database if needed
// if you don't want to save changes in layer database, do not call this method
pLayer->Commit();

Fastest method of accessing all map objects intersected with specific rectangle

This method provide very fast access to map objects intersected with specific rectangle. Like fast iteration technic above, you must iterate through nodes and none-node objects separately. Furthermore, you must define a global function as "search callback".

First we define a search callback function:

bool SearchCallback(CMapObject* pObj) 
{
	//call InitMetaData only in real need. This is a bit slow function
	pObj->InitMetaData();
	if(pObj->GetType() != node) 
		pObj->SetLineColor(GREEN);
	else
		pObj->GetObjectProperty()->SetNodeColor(GREEN);
	pObj->Commit();
	//free memory to avoid memory leeks
	FREE(pObj);
	return false;//continue search; to interrupt search, return true
}

Iterate through all none-node objects

Call CMapLayer's method FindObjectByXTree:

pLayer->FindObjectByXTree(0, GetMap()->GetViewportRect(), SearchCallback);

In this sample code we look for all none-node objects in current map window, not ignoring small objects, and use SearchCallback as search callback method.

Iterate through all node objects

Call FindNodeByKdTree method:

pLayer->FindNodeByKdTree(GetMap()->GetViewportRect(), SearchCallback);

In this sample code we look for all node objects in current map window, using SearchCallback as search callback method.