There are three ways to do this:
The first two can be done without Creator:
1) Use the fltComment attribute of any node (except fltVertex) to add "string" data to the node.
2) Add a "binary" extension by building a data extension site in a plugin (see volume 2 of the OpenFlight API Users Guide for more info on how to do that)
The last one can be done without Creator also but is a bit easier in Creator:
3) Build an "easy" OpenFlight extension. There is a window in Creator that lets you do this easily. You can do this with just the OpenFlight API also. The procedure for this is also described in volume 2 of the OpenFlight API Users Guide.
Thanks! That got me started in the right direction.
Incidentally, for others, there is a great example to be found in the header function comments for mgExtensionMakeGUID in mgapiextension2.h.
I've got this written, but I've no way to know if the polygons have the attributes I've set. I've attached it, and would appreciate if you could open it up in Creator to see if there are any Extension Fields set on any of the polygons.
Also, I don't really get how the Site Extension and subsequently the Fields get attached to the DB and/or individual polygons. Is the mgExtensionSiteAdd call and then using the GUID all that is need to create a site? I do later make the various mgExtensionFieldSetter calls, but how does the API know what DB the site/fields are associated with, since they don't appear to be nodes added to the DB? Do they go "out of scope" at the end of my function below? I feel like I'm missing a step somewhere.
code:
OfAttrNameGuidMap OfAppManager::buildClassAttributes(const ptr_fdb_class_spec& cls,
int db_node_type)
{
// This method builds the OpenFlight Extension Site and attribute Fields
// using the attribute type that is specified by the FDB schema. A map keyed
// on the GUID assigned to each of the attribute names is returned.
OfAttrNameGuidMap attr_name_guids;
// create the new extension site and give it a namestd::string class_site_guid(mgExtensionMakeGUID());
mgExtensionSiteAdd(class_site_guid.c_str());
UnicodeString class_site_name(cls->class_name);
mgExtensionSiteSetName( class_site_guid.c_str(),
(Unicode::convertToLocaleString(class_site_name)).c_str() );
//Loop through all attributes in the class specifiedfdb_class_attr_rec* attr = cls->ftr_attrs;
while(NULL != attr)
{
// create the new extension field and give it a name
std::string attr_field_guid(mgExtensionMakeGUID());
UnicodeString attr_field_name(attr->aname);
mgExtensionFieldSetName( attr_field_guid.c_str(),
(Unicode::convertToLocaleString(attr_field_name)).c_str() );
// Figure out the attribute type, and and build the Extension Site Fields.// See mgapistd.h enum tagtype for mapping.
switch(attr->atype)
{
case INT_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_INT);
break;
}
case FLOAT_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_FLOAT);
break;
}
case DOUBLE_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_DOUBLE);
break;
}
case ASCII_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_TEXT);
break;
}
case ENUMER_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_ENUM);
break;
}
case DATE_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_TEXT);
break;
}
case DATETIME_TYPE: {
mgExtensionFieldSetType(attr_field_guid.c_str(), MTYPE_TEXT);
break;
}
case UNKNOWN_TYPE:
default: {
attr_field_guid = "";
break;
}
}
if (!attr_field_guid.empty())
{
// This field will "extend" nodes of the type passed in
mgExtensionFieldSetAttach (attr_field_guid.c_str(), db_node_type);
mgExtensionFieldAdd(class_site_guid.c_str(), attr_field_guid.c_str());
attr_name_guids[attr_field_name] = attr_field_guid;
}
attr = attr->next;}
return attr_name_guids;}
Iââ¬â¢ve got this written, but Iââ¬â¢ve no way to know if the polygons have the attributes Iââ¬â¢ve set. Iââ¬â¢ve attached it, and would appreciate if you could open it up in Creator to see if there are any Extension Fields set on any of the polygons.
Yes some of the nodes in this file do have extension data attached. Note, however that Creator will not show this without the schema file so I had to inspect the OpenFlight file in other ways. With the schema file, Creator will show the data but without the schema, Creator keeps the data private. You can check this yourself with mgExtensionFieldDefined. Simply call this function on the node you suspect has a specific data extension and it will return MG_TRUE if the data is "on" that node, MG_FALSE otherwise. You can use other similar functions to further interrogate the extension data on your nodes.
Also, I donââ¬â¢t really get how the Site Extension and subsequently the Fields get attached to the DB and/or individual polygons
The Extension Site and Fields don't get attached to the db in the OpenFlight file. Only the extension data actually attached to nodes (in your case polygons) goes in the db file. The site and field information typically resides in the "schema" that is kept separate from the file in which it is used. This may seem strange but consider if you had thousands of files all using the same schema, you might not want the schema repeated in each file. In this way, the schema is used like a "map or legend" to decode the extension data found in the files.
Apps that support OpenFlight extensions have to "load the schema" at startup. In Creator the "schema" is an XML file that is loaded at model time and is used as a "map" of sorts. This schema file contains the GUIDs of the sites and fields. And the GUIDs contained in this schema file NEVER change. The GUID is used to identify extension data. Once you refer to it by one GUID you have to refer to it by that GUID forever.
In stand alone apps "loading the schema" is a bit more tricky. The function you show in your post is the function that "loads the schema" (extension site and fields) programmatically. Except it has one serious flaw. It is calling mgExtensionMakeGUID() to make NEW guids to use for its Site and Fields. This means each time you run your code, you get a new set of GUIDs. This won't work. Files written yesterday (with this function setting up the GUIDs) would use one set of GUIDs and files written tomorrow (in a separate, new invocation of your program) would use a different set of GUIDs. Your extension site and field GUIDs must never change. You can use this function "to load your schema" but should use constant GUIDs in place of calling mgExtensionMakeGUID(). This is easy to do... Create a new program that simply calls mgExtensionMakeGUID() and prints out the string. Do this to get a GUID for your site and do this once additionally for each of your fields. Record these strings and put these #defines in your code like this:
#define MY_SITE_GUID "10F6212E-9769-43bf-9D06-A9E162F1BCE9"
#define MY_FIELD1_GUID "922E5552-5E83-483e-9BA5-F3DA72D21A5B"
#define MY_FIELD2_GUID "BC146DFE-BA85-44eb-911E-599111048C5A"
...
#define MY_FIELDN_GUID "65878F4C-308F-43eb-B50F-54B27EFAE4F4"
BTW, don't use these exact GUIDs, make your own ;-)
Then in your code replace:
std::string class_site_guid(mgExtensionMakeGUID());
mgExtensionSiteAdd(class_site_guid.c_str());
with:
mgExtensionSiteAdd(MY_SITE_GUID);
and do the same sort of thing for when you set up your fields (mgExtensionFieldAdd,etc). Use MY_FIELD1_GUID, MY_FIELD2_GUID, ... MY_FIELDN_GUID) instead of calling mgExtensionMakeGUID() for the GUID.
The key here is to create a set of GUIDs one time and use those GUIDs always. Don't make new GUIDs each time.
Note, however that Creator will not show this without the schema file so I had to inspect the OpenFlight file in other ways.
I don't understand how to write the schema file, or otherwise provide it for Creator to access. As you I think you confirmed, I thought I was doing that in my function, but is an XML file supposed to be written out, or is the schema imbedded in the FLT file?
And the GUIDs contained in this schema file NEVER change... The function you show in your post is the function that ââ¬Åloads the schemaââ¬Â (extension site and fields) programmatically. Except it has one serious flaw. It is calling mgExtensionMakeGUID() to make NEW guids to use for its Site and Fields.
The structure of my source data is below,and I'm trying to convert it to OpenFlight. Now, I don't see the problem with creating a new Site GUID for every class, and new Field GUIDs for every attribute, saving the relationship in a Map, and then using the Map to attach Fields to Polygons. This is what I do in later on in code outside the function, but I'm still foggy on how the Site Extension structure persists after I leave my function if it is not attached to the DB, and it is not written out to a file.
Root
---Class1
------Attribute1
------Attribute2
---Class2
-------Attribute1
-------Attribute2
Files written yesterday (with this function setting up the GUIDs) would use one set of GUIDs and files written tomorrow (in a separate, new invocation of your program) would use a different set of GUIDs. Your extension site and field GUIDs must never change. You can use this function ââ¬Åto load your schemaââ¬Â but should use constant GUIDs in place of calling mgExtensionMakeGUID().
I can't do this. I don't know everything about the data at compile time. I have to dynamically load the source data, inspect it for attributes, build the Site Extension and Fields for each attribute of each class of feature at run time.
I thought the idea was that when my output FLT files are eventually read back in they contain a Site Extension, or many, with Fields, and that by extracting the GUID for the SE you can get the Fields, and by extracting the Field GUIDs you can get the attribute values for each polygon. Aren't there API calls for doing all of this when reading in a FLT file?
After an offline meeting with Marc, we clarified what he is trying to do here. He is converting his database to OpenFlight and looking for a way to add extension data "on the fly" to the OpenFlight scene graph. That is, he does not know, a priori, the extension data he wants to store from his original database format. He discovers this data as he parses his original database format while converting it to OpenFlight.
After some discussion, we proposed a different way for him to approach this. He could create a Site GUID and a single Field GUID for an XML string type extension on the OpenFlight nodes. Then the "data" for this XML extension would be the "on the fly" data bits he finds in his original database.
Hope this helps anyone following along here.
Craig
Let's say I want to add a name string, date or some sort of ID number to a polygon. Is there a way to add some custom information like this to a polygon?