The DtDataBank contains simulation-specific and element-specific data elements.
However there is substantial overlap - VR-Link driver's Marking Text is an element (that comes from that driver) Display Name. Element Data is, for the most part, static, and created when the Element itself is created. Simulation Data, on the other hand, contains both static and dynamic data.
Recently, we have added more of the static simulation data to the element data as element attributes, because element data is easier to work with and faster/cheaper to retrieve. In addition to the the already existing Display Name attribute, there is now a Connection ID attribute and a Connection Entity Type attribute. These are whatever a particular connection uses for an ID and entity type, in string form. For example, an element from a DIS connection might have a connection ID of "3001:1:1" and a connection entity type of "1:225:1:1:1:0:0". An element created by a CIGI connection, on the other hand, might have an connection ID of "5" and a connection Entity Type of "17".
It is common for users who are used to working in a DIS or HLA environment to want to look up elements by a connection ID or Marking Text, for example. Connection objects makes that much easier to do.
The exampleConnectionObjects example shows the signal that is raised with all the elements whose attribute data has been received that frame; elements can be added to indices or sets based on attribute data at that time. It builds an index of element IDs to Marking Text (Display Name) and vice versa. The example can easily be extended to build similar indices using connection ID attributes.
#include <boost/unordered_map.hpp>
namespace makVrv
{
: myDe( de )
{
myDe.dataBank().elementData().signal_elementsInitialized.connect(
boost::bind( &DtConnectionObjects::slot_elementsReadyToProcess,
this, _1 ) );
myDe.dataBank().elementData().signal_elementsToBeRemoved.connect(
boost::bind( &DtConnectionObjects::slot_elementsRemoved,
this, _1 ) );
}
DtConnectionObjects::~DtConnectionObjects()
{
myDe.dataBank().elementData().signal_elementsInitialized.disconnect(
boost::bind( &DtConnectionObjects::slot_elementsReadyToProcess,
this, _1 ) );
myDe.dataBank().elementData().signal_elementsToBeRemoved.disconnect(
boost::bind( &DtConnectionObjects::slot_elementsRemoved,
this, _1 ) );
}
DtSceneObject* DtConnectionObjects::sceneObjectFromSceneObjectId(
DtUniqueID sceneObjId )
{
DtAgentUpdateResolverInterface* resolver = myDe.agentManager().findUpdater( sceneObjId );
if( resolver )
{
return resolver->castObjectTypeFromUpdater<DtSceneObject>( "DtSceneObject" );
}
return 0;
}
DtSceneObject* DtConnectionObjects::sceneObjectFromElementId(
DtElementID elementId,
int modelSet )
{
DtElementData::SceneObjectIdList idList;
myDe.dataBank().elementData().getSceneObjectIds( elementId, idList, modelSet );
if ( idList.size() == 0 )
{
return 0;
}
return sceneObjectFromSceneObjectId( idList.front() );
}
const DtConnectionObjects::DisplayNameToElementIdMap& DtConnectionObjects::displayNames() const
{
return myDisplayNameToElementIdMap;
}
const DtConnectionObjects::SceneObjectMap& DtConnectionObjects::sceneObjects() const
{
return mySceneObjectMap;
}
{
DisplayNameToElementIdMap::const_iterator iter = myDisplayNameToElementIdMap.find( displayName );
if ( iter != myDisplayNameToElementIdMap.end() )
{
return iter->second;
}
}
{
ElementIdToDisplayNameMap::const_iterator iter = myElementIdToDisplayNameMap.find( elementID );
if ( iter != myElementIdToDisplayNameMap.end() )
{
return iter->second;
}
return "";
}
{
DtElementEntry* entry = myDe.dataBank().elementData().findElement( elementID );
if ( entry )
{
entry->findAttribute( DtElementAttributes::ConnectionObjectID ) );
if ( objectIdAttr )
{
return objectIdAttr->value();
}
}
return "";
}
{
DtElementEntry* entry = myDe.dataBank().elementData().findElement( elementID );
if ( entry )
{
entry->findAttribute( DtElementAttributes::ConnectionObjectType ) );
if ( objectTypeAttr )
{
return objectTypeAttr->value();
}
}
return "";
}
DtSceneObject* DtConnectionObjects::findSceneObject(
DtElementID elementId )
const
{
SceneObjectMap::const_iterator iter = mySceneObjectMap.find( elementId );
if ( iter != mySceneObjectMap.end() )
{
return iter->second;
}
return 0;
}
void DtConnectionObjects::slot_sceneObjectToBeDeleted(
const DtUniqueID& sceneObjId )
{
DtSceneObject* deletingObject = sceneObjectFromSceneObjectId( sceneObjId );
if ( deletingObject )
{
deletingObject->signal_sceneObjectToBeDeleted.disconnect(
boost::bind(
&DtConnectionObjects::slot_sceneObjectToBeDeleted, this, _1 ) );
mySceneObjectMap[elementId] = 0;
}
}
void DtConnectionObjects::slot_elementsReadyToProcess(const DtElementData::ElementIdList& elements)
{
DtElementData::ElementIdList::const_iterator curIter = elements.begin();
DtElementData::ElementIdList::const_iterator endIter = elements.end();
for ( ; curIter != endIter; ++curIter )
{
DtElementEntry* entry = myDe.dataBank().elementData().findElement( *curIter );
if ( entry )
{
switch (entry->type() )
{
case DtElementEntry::Entity:
case DtElementEntry::Aggregate:
case DtElementEntry::GraphicShape:
case DtElementEntry::GraphicPoint:
{
entry->findAttribute( DtElementAttributes::DisplayName ) );
if ( displayNameAttr )
{
DisplayNameToElementIdMap::iterator dnIter = myDisplayNameToElementIdMap.find( displayName );
if ( dnIter != myDisplayNameToElementIdMap.end() )
{
myDisplayNameToElementIdMap.erase( dnIter );
}
myDisplayNameToElementIdMap[displayName] = entry->elementID();
ElementIdToDisplayNameMap::iterator eiIter = myElementIdToDisplayNameMap.find( entry->elementID() );
if ( eiIter != myElementIdToDisplayNameMap.end() )
{
myElementIdToDisplayNameMap.erase( eiIter );
}
myElementIdToDisplayNameMap[entry->elementID()] = displayName;
}
DtSceneObject* sceneObject = sceneObjectFromElementId(
entry->elementID(), 0 );
if ( sceneObject )
{
SceneObjectMap::iterator soIter = mySceneObjectMap.find( entry->elementID() );
if ( soIter != mySceneObjectMap.end() )
{
DtSceneObject* existingSceneObj = soIter->second;
if ( existingSceneObj )
{
existingSceneObj->signal_sceneObjectToBeDeleted.disconnect(
boost::bind(
&DtConnectionObjects::slot_sceneObjectToBeDeleted, this, _1 ) );
}
mySceneObjectMap.erase( soIter );
}
mySceneObjectMap[entry->elementID()] = sceneObject;
sceneObject->signal_sceneObjectToBeDeleted.connect(
boost::bind(
&DtConnectionObjects::slot_sceneObjectToBeDeleted, this, _1 ) );
}
signal_entityAdded( entry->elementID() );
}
break;
default:
break;
}
}
}
}
void DtConnectionObjects::slot_elementsRemoved( const DtElementData::ElementIdList& elements )
{
DtElementData::ElementIdList::const_iterator curIter = elements.begin();
DtElementData::ElementIdList::const_iterator endIter = elements.end();
for ( ; curIter != endIter; ++curIter )
{
DtElementEntry* entry = myDe.dataBank().elementData().findElement(*curIter);
if ( entry )
{
if ( entry->type() == DtElementEntry::Entity || entry->type() == DtElementEntry::Aggregate )
{
signal_entityRemoved( *curIter );
ElementIdToDisplayNameMap::const_iterator eiIter = myElementIdToDisplayNameMap.find( *curIter );
if ( eiIter != myElementIdToDisplayNameMap.end() )
{
DisplayNameToElementIdMap::const_iterator dnIter = myDisplayNameToElementIdMap.find( eiIter->second );
if ( dnIter != myDisplayNameToElementIdMap.end() )
{
myDisplayNameToElementIdMap.erase( dnIter );
}
myElementIdToDisplayNameMap.erase( eiIter );
}
SceneObjectMap::const_iterator soIter = mySceneObjectMap.find( *curIter );
if ( soIter != mySceneObjectMap.end() )
{
DtSceneObject* existingSceneObj = soIter->second;
if ( existingSceneObj )
{
existingSceneObj->signal_sceneObjectToBeDeleted.disconnect(
boost::bind(
&DtConnectionObjects::slot_sceneObjectToBeDeleted, this, _1 ) );
}
mySceneObjectMap.erase( soIter );
}
}
}
}
}
}
#include <boost/unordered_map.hpp>
#include <matrix/vlVector.h>
#include <iostream>
namespace makVrv
{
: makVrv::DtDriver( am, "DtConnectionObjectsDriver" )
, myConnectionObjects( new DtConnectionObjects( am.de() ) )
{
}
DtConnectionObjectsDriver::~DtConnectionObjectsDriver()
{
DtConnectionObjectsDriver::onStop();
delete myConnectionObjects;
myConnectionObjects = 0;
}
const std::string& DtConnectionObjectsDriver::className()
const
{
}
bool DtConnectionObjectsDriver::onStart()
{
myConnectionObjects->signal_entityAdded.connect(
boost::bind( &DtConnectionObjectsDriver::slot_entityAdded,
this, _1 ) );
myConnectionObjects->signal_entityRemoved.connect(
boost::bind( &DtConnectionObjectsDriver::slot_entityRemoved,
this, _1 ) );
return true;
}
bool DtConnectionObjectsDriver::onStop()
{
myConnectionObjects->signal_entityAdded.disconnect(
boost::bind( &DtConnectionObjectsDriver::slot_entityAdded,
this, _1 ) );
myConnectionObjects->signal_entityRemoved.disconnect(
boost::bind( &DtConnectionObjectsDriver::slot_entityRemoved,
this, _1 ) );
return true;
}
bool DtConnectionObjectsDriver::onTick()
{
return true;
}
void DtConnectionObjectsDriver::slot_entityAdded(
DtElementID entity )
{
std::string displayName = myConnectionObjects->findDisplayName( entity );
std::string objectId = myConnectionObjects->findObjectId( entity );
std::string objectType = myConnectionObjects->findObjectType( entity );
std::cout
<< "Added " << displayName << std::endl
<< " ID " << objectId << std::endl
<< " Type " << objectType << std::endl;
}
void DtConnectionObjectsDriver::slot_entityRemoved(
DtElementID entity )
{
std::string displayName = myConnectionObjects->findDisplayName( entity );
std::cout
<< "Removed "
<< displayName
<< std::endl;
}
void DtConnectionObjectsDriver::slot_postUpdate(
DtElementID entity )
{
DtSceneObject* sceneObject = myConnectionObjects->findSceneObject( entity );
std::string displayName = myConnectionObjects->findDisplayName( entity );
if ( sceneObject )
{
DtVector position;
sceneObject->getPosition(0, position );
std::cout
<< displayName << " Position: "
<< position[0] << " " << position[1] << " " << position[2]
<< std::endl;
}
}
}