Start a new topic

Setting fltPointPosition attribute of a fltPoint

In creating a point node, I get a failure when setting the position using the following code


int nAttributes;

mgrec* point;


point = mgNewRec (fltPoint);
ok = mgAttach (object,point);

ASSERT(ok);

double icoord1[3] ={8.0, 9.0, 15.0};
nAttributes = mgSetAttList (point , fltPointPosition , icoord1 ,MG_NULL);


the return value nAttributes is 0 (zero) when it should be 1, however, the point appears to have the position set correctly.





I believe Maxwell meant to reply back to this forum (but opened up a ticket instead). 


Here is his response:


=====================================


Hello again Steve,


Yes, I saw that note in the developers guide, and I have been using the data dictionary to get the proper variable types correct.


But I really appreciate your help !


cheers,

Max

Max,

Another tricky thing about mgGetAttList (perhaps you've discovered this already) is that the value address you pass to "receive" an attribute value must match exactly the type declared for that attribute code in the OpenFlight Data Dictionary. Passing the address of a "double" for example when the attribute is type "float" or passing an "int" address for an attribute whose type is "short" or "char" will result in errors. The best case is the value will not be correct. The worse case is that memory will be overwritten and that could cause a crash or other severe error in your program. This will happen, for example, when you pass the address of a "float" (4 bytes) to receive a "double" value (8 bytes). This is a common "gotcha" for OpenFlight API users so be beware. 


Note that mgSetAttList does not have this problem because C++ compilers coerce parameters to varargs functions to either "int" or "double". That is, integer values shorter than 4 bytes are passed as 4 byte "int" (signed or unsigned) and 4 or 8 byte floating point values are passed as 8 byte "double". 

Hello Steve,

 

Thanks for the advice; works fine.  That information was not clear in the developers guide, but all programming is a learning session.

 

Max

Oh, and I can't explain how mgSetAttList would have set the values of the nested record using the array you passed. I don't see a path through the code to account for this "happy" accident ;-)

mgSetAttList (as well as mgGetAttList) is only meant to be used for attribute codes. fltPointPosition is a record code. An attribute code identifies a field of a record that has a single value, like integer, double, string, etc. As the name implies, a record code identifies a structure in the OpenFlight Data Dictionary comprised of other records and/or attributes.


fltPointPosition is a fltCoord3d record. There are different ways to set a fltPointPosition of a fltPoint node. Note that the functions that follow apply to setting any nested fltCoord3d record. Use similar functions to set other nested record types. The easiest way is using the convenience function mgSetCoord3d as shown here:  

mgrec* point = mgNewRec (fltPoint);
mgbool ok = mgAttach (object, point);
double icoord1[3] = {8.0, 9.0, 15.0};
ok = mgSetCoord3d (point, fltPointPosition, icoord1[0], icoord1[1], icoord1[2]);

You can use mgSetAttList but to do so you must specify the nested attribute codes inside the fltPointPosition nested record as shown here:   

mgrec* point = mgNewRec (fltPoint);
mgbool ok = mgAttach (object, point);
double icoord1[3] = {8.0, 9.0, 15.0};
int nAttributes = mgSetAttList(point, fltCoord3dX, icoord1[0], fltCoord3dY, icoord1[1], fltCoord3dZ, icoord1[2], MG_NULL);

Note that mgSetAttList searches nested records for the first matching attribute code. If fltPoint contained two or more fltCoord3d nested records, mgSetAttList could only be used on the first nested record. It would never find the second one !!


If a parent record contained two or more nested records of the same type (in this case fltCoord3d), here is yet another way to set attributes on a nested record using mgGetAttRec:   

mgrec* point = mgNewRec (fltPoint);
mgbool ok = mgAttach (object, point);
double icoord1[3] = {8.0, 9.0, 15.0};
// get a pointer to the nested record
mgrec* attRec = mgGetAttRec (point, fltPointPosition);
// now you can use mgSetAttList directly on the nested record without 
// worry of ambiguity for finding fltCoord3dX, fltCoord3dY or fltCoord3dZ
int nAttributes = mgSetAttList(attRec , fltCoord3dX, icoord1[0], fltCoord3dY, icoord1[1], fltCoord3dZ, icoord1[2], MG_NULL);

Note that I did not check these code snippets for correct compilation. I apologize if they contain syntax errors. Hopefully you get the idea. Let us know if you have further questions.



Login to post a comment