VR-Forces 4.3 Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
15.4 - Using Vector Networks

Table of Contents

A vector network is a structure of vectors and points used to represent features in the database such as rivers, roads, and buildings.

A DtTerrainInterface represents the vector network in the following nodes:

Features are represented in the vector network using the following nodes:

Note
DtNetworkSegment is an implementation detail. It is exposed to provide you with the underlying representation of the edge, where necessary, but it is recommended that you use the point interface exposed by the DtNetworkEdge.

Network nodes and edges have a DtSpecification (specification.h) associated with them. The specification holds information about the feature, such as the number of floors it has (in the case of a building), the height and width of the feature, and identifiers, such as DFAD or SEDRIS codes. For more information about specifications, please see 15.4.3 Feature Specifications.

15.4.1 Linear Features

Linear features, such as roads and rivers are made up of one or more DtNetworkEdge objects. A DtNetworkEdge is made up of a start DtNetworkNode, an end DtNetwork-Node, and a series of points that define the smallest straight segments of the edge. (This is why, internally, the edge is represented as both a series of points and as a series of DtNetworkSegments.) A DtNetworkSegment represents a portion of a network that can be approximated by a line segment (vector).

linearfeature_edge.png
Linear Feature (Edge)

Edges have a direction. The sequence of segments that comprise an edge never intersect one another. A DtNetworkSegment never exists by itself in the vector network - it is always part of a DtNetworkEdge. Edges can be connected to one another (or themselves) at their endpoints.

Note
It is recommended that you use the point interface, and not access segments directly, as they are considered to be an implementation detail and could change in the future.

15.4.1.1 Iterating Through the Points in an Edge

To iterate through the points of an edge, ask the edge for a DtNetworkEdgeTraverser object. You must specify whether or not to respect the directionality of the edge. If you ignore the directionality, both a forward and backward traverser may be created. However, if you respect the directionality, then for a unidirectional street, only a forward edge traverser can be created.

Once a traverser is created for an edge, ask for a DtNetworkEdgePointIter over that edge. The point iterator allows you to iterate over the points contained in the edge. The DtNetworkEdgePointIter abstracts away the direction of traversal. Thus, when moving both forwards and backwards along an edge, incrementing the DtNetworkEdgePointIter returns an iterator pointing to the next point as appropriate.

15.4.2 Areal Features

Areal features are represented by a DtNetworkEdge that forms a closed figure (initial and final point are the same), plus an additional point located approximately in the center of the feature.

arealfeature.png
Areal Feature

Each area has its own specification entry, which must include the extents of a bounding box.

15.4.3 Feature Specifications

A DtSpecification represents the set of characteristics associated with a feature in the vector network. A specification can include any number of attributes used to describe the feature. For example, the specification for a building might include the number of floors, while the specification for a river might include width and water level. The DtSpecificationAttribute class (specAttrib.h) represents the individual attributes held in a DtSpecification. A DtSpecificationAttribute has a string label and a value. Derived kinds of DtSpecificationAttribute are defined for integer, real, and string values.

You can look up an attribute in a specification by its string label. For example, to get the ECC code (a SEDRIS string identifier) for a specification attribute, do the following:

const DtSpecificationStringAttribute* group = (const DtSpecificationStringAttribute*)spec.attribute("ECC");
if(group)
{
DtInfo("ECC = %s\n", group->value());
}

The ECC code is one of a number of specification attributes typically defined in terrain databases. Please see The MAK Specification Model in MAK Terrain Database Tool Users Guide for a list of attribute label/value pairs used in MAK terrain databases.

A DtSpecification has some predefined attributes. They are fundamental attributes that can be associated with any feature. The API has methods for setting and retrieving these attributes directly. The table lists basic mutator methods.

Attribute Accessor and Mutator Methods
Accessor/Mutator Description
setLength(), length() Length of the feature.
setWidth(), width() Width of the feature.
setColor(), color() RGB color.
setVisibility(), visibility() Boolean is visible on/off.

The length and width attributes can also be accessed by the GDB_Length and GDB_Width attribute labels.

The DtSpecification class allows any number of additional DtSpecificationAttributes to be defined and added to it. For example, to create and configure a specification for a building, do the following:

DtSpecification spec;
// set values for the predefined attributes
spec.color(DtColor(100,100, 100, 0));
spec.setLength(100);
spec.setWidth(10);
// Add a "Type" attribute to the specification, with a value of "Building"
DtSpecificationStringAttribute sattr;
sattr.setLabel("Type");
sattr.setValue("Building");
spec.addAttribute(sattr);

DtSpecification stores the attributes in a hash list indexed by label. To modify a value, add the attribute again with a new value and it will replace the old one.

If you create a DtSpecification for an areal vector feature, that is, the specification has a FeatureType = 2 attribute, then the specification must also contain the following attributes:

Each of these attributes is a double. They represent the extent of the areal feature. If these attributes are not present, VR-inTerra uses 0.0, which may result in unintended consequences.

15.4.4 The MAK Specification Model

MAK has developed its own model based on the Digital Feature Analysis Data (DFAD) specification and SEDRIS enumerations. While you can develop your own specification model through the API, the MAK specification model is already in place (all of our terrain readers use this model). You can use it as-is, extend it, or develop your own scheme for classifying and describing feature data. Please see The MAK Specification Model in MAK Terrain Database Tool Users Guide for a description of the specification attributes used in the MAK specification model.

15.4.5 Querying the Vector Network

You can query the vector network to ask for intersections with features. To do this you need to provide a DtVectorNetworkRecord (vecNetwrkRecord.h) parameter, in which you can specify the criteria for selecting terrain features along the intersection chord. Intersected vector network features that meet the criteria in the record parameter are returned in a DtVectorNetworkIntersectionRecord (vecNwrkIntRec.h). For example, to query for the terrain skin intersection and for all of the vector network features along the chord, do the following:

// Configure vector network record parameter to only select roads
DtVectorNetworkRecord dataRec;
DtSpecificationStringAttribute specAttribute;
specAttribute.setLabel("DtFeatureGroup"); // MAK-defined DtGroup attribute
// used to classify features
specAttribute.setValue("MAK010"); // roads
dataRec.addEqualCondAttr(specAttribute);
DtVectorNetworkIntersectionRecord intersectionRec;
// Calculates intersection with terrain geometry and vector network
tdb2.intersect(chord, isectPoint, intersectionTime, &dataRec, &intersectionRec);
Note
Querying the vector network is a bit different from querying the terrain skin. While the interface presented by both is named intersection, what is actually occurring with the vector network is not intersection, but rather selection based on criteria. As a result, to perform an actual intersection with vector features, the features must be selected from the vector network as described in this section, and then an actual intersection test must be done, using the properties of the features that define an intersectable object, presumably a volume (width, length, height).

15.4.6 Testing for All of the Terrain Intersections Along a Chord

You can perform intersection tests on the terrain database that return all of the points along a given chord that intersect the terrain database. This applies to terrain skin as well as features. Please see terrainInterface.h for the set of all available intersection methods.

15.4.7 Using Metrics to Query the Vector Network

In addition to the intersection tests discussed in the previous sections, you can make more customized queries to the vector network using metrics. Metrics provide a mechanism to select elements from the vector network based on:

DtMetric (metric.h) is the abstract base class for metrics. It allows feature attributes to be evaluated as equal, different, greater than, and lesser than. You can use the following predefined metrics to query the vector network:

You can use these metrics to evaluate the vector network based on feature specification and range or distance to a point or chord of interest. They calculate intersection against the vector network and calculate paths (in the sense of paths through a graph) using the vector network.

For example, to retrieve all of the trees within range of a location:

// Create a range metric - we will use this to select features (nodes)
// from the vector network that fall within range of a location.
DtRangeNetworkNodeMetric nodeMetric;
// Create a specification attribute - we will use this to select
// the types of nodes in our metric. Select only those features having
// the MAK DtGroup specification of type "MAK040" (vegetation)
DtSpecificationStringAttribute sattr;
sattr.setLabel("DtFeatureGroup");
sattr.setValue("MAK040");
// Set the location of the center of our search for trees, in meters
nodeMetric.setCenterOfInterest(DtPoint(2000, 2000, 0));
// Set the range of the search, in meters
nodeMetric.setMaxRange(45);
// Take EvalInZ attribute into account in distance calculations
nodeMetric.setEvalInZ(true);
// Add a test for the specification attribute (that is, does the feature
// have a DtGroup attribute with a value of "MAK040"?)
nodeMetric.addEqualCondition(sattr);
// Query the vector network for the list of nodes using our metric. It
// returns all of the trees within 45 meters of location (2000, 2000, 0).
DtVectorNetwork* vectorNetwork = terrainInterface()->vectorNetwork();
DtList nodeList;
myVectorNetwork->collectAllNodes(nodeMetric, nodeList);

The node list contains pointers to all of the DtNetworkNode objects that meet the requirements specified in nodeMetric. The list is sorted in order of closest to furthest from the center of interest. You can add any number of specification attributes to your metric, to further refine your search.

15.4.8 Synchronous and Asynchronous Calls with Paged Terrains

Some terrain types, such as streaming terrain and MetaFlight, utilize paging to limit the amount of terrain loaded by the application at one time. Typically the terrain is broken up into pages along a spatial grid and the pages are loaded on demand when an intersection method requires the data. If the interface was to do nothing special with paged terrains, when an intersection landed in an area where the data was not yet loaded, the system would have to wait for the data to be loaded. In some cases this may take a fairly long time and lead to undesirable results for the simulation. The DtTerrainInterface can cope with the paged terrains in two ways to help minimize the occurrence of missed pages and long intersection times.

The first method is if the user can inform the terrain interface of its desire to use an area that is not loaded ahead of time. This is done through the preloadTerrainAreas() method. Calling this method informs the interface of the areas of the terrain that will be required and the interface will start loading those areas in the background. However, there is no guarantee that those areas will be loaded immediately and be available for intersection calls. In this case the user can perform the intersection calls asynchronously.

To make a terrain method asynchronous the caller must provide a Boolean in the intersection method called DataAvailable. When this Boolean is present and the interface is forced to make a call that would cause it to load a page, the method will return immediately and DataAvailable will be set to false. This indicates that the call has neither succeeded nor failed, just that it will take some time to load the page. The caller then can perform other calls and return to this call at a later time when the data may have had a chance to load. When DataAvailable is not present the call will always block, waiting for the call to end no matter how long it takes.

The following code shows a thread that waits for the data to arrive without consuming the cpu during its wait.

int maxWait = 10;
double height = 0.;
while (true)
{
bool dataAvailable = false;
double height = terrainInterface.terrainHeightAboveSeaLevel(localLocation, &dataAvailable);
if (!dataAvailable)
{
--maxWait;
if (maxWait == 0)
{
break;
}
DtSleep(0.5);
}
else
{
break;
}
}

The code gives the terrain interface 10 tries and sleeps between each try, allowing other threads to continue. Also note that while the call to terrainHeightAboveSeaLevel() is only different by the inclusion of the DataAvailable boolean, there needs to be a lot more surrounding code to deal with the case when the data is not available.

The terrain interface also has a method called setAssertOnBlockingTerrainCalls(). By setting this value to True, the interface will assert every time a terrain call is made that is called in a non-asynchronous manner. This is useful for testing to find the calls that are made to the terrain that are blocking. Additionally each call can be set to override the blocking assert when the blocking aspect of the call is the required functionality.

[<< Querying the Terrain Interface] [Home] [Top of Page] [Terrain Implementations >>]


Document ID: Generated on Wed Mar 11 21:20:57 EDT 2015 from SVN revision 150940
Copyright © 2005-2014 VT MÄK. All Rights Reserved (www.mak.com)