According to "File Geodatabase API 1.2 now available":
What�??s new at 1.2:
* Structure definitions for curves (CircularArcCurve, BezierCurve, EllipticArcCurve).
In v1.2, util.h includes class definitions for Curves:[INDENT]class EXT_FILEGDB_API Curveclass EXT_FILEGDB_API CircularArcCurve : public Curve[/INDENT]etc, but there's no indication as to how we should use them. No API function uses these classes, so I can't get/set a curve object from/to a shape.I can't just use them as structs and cast the byte pointer from MultiPartShapeBuffer::GetCurves because:* The classes/structs are not packed, so I can't guarantee alignment with the byte pointer data* The members include ints, whose size is machine dependent, rather than the fixed size int32* Objects derived from the base class Curve include the virtual function table pointer.Is there a better way than my current methodology, which is to copy the structure definitions from doc\html\extended_shape_buffer_format.pdf and use them thus:
namespace FileGDBAPI
{
/*-----------------------------------------------------------------------------
Curve structure definition, from Extended Shape Buffer Format, February 9, 2012 (doc\html\extended_shape_buffer_format.pdf)
The document uses "long" for some members, but we use int32 (from FileGDBCore.h) here to ensure a fixed size.
(The necessary size of a "long" can be deduced from footnote 12.)
*/
#pragma pack(push, 1)
struct WKSPoint
{
double x, y;
};
struct SegmentArc
{
union {
WKSPoint centerPoint; // If IsPoint is 0. Also, it is ignored if
// IsLine is 1.
double angles[2]; // If IsPoint is 1: start and central angle
// centerPoint = endPoint
};
int32 Bits; // Contains, among others, bits for IsPoint, IsLine ...
};
struct esriSegmentModifier
{
int32 startPointIndex,
/* enum esriSegmentType */ segmentType;
union {
SegmentArc arc;
SegmentBezierCurve bezierCurve;
SegmentEllipticArc ellipticArc;
// SegmentOther otherKindsOfSegment;
// ...
} segmentParams;
};
...
#pragma pack(pop)
} // namespace FileGDBAPI
// Build a vector of curves from my input data
vector<esriSegmentModifier> vCurves;
for (...)
{
esriSegmentModifier modifier;
modifier.startPointIndex = ...
modifier.segmentType = esriSegmentArc;
modifier.segmentParams.arc.centerPoint.x = ...
modifier.segmentParams.arc.centerPoint.y = ...
modifier.segmentParams.arc.Bits = ...
vCurves.push_back(modifier);
}
// Put the curves into a MultiPartShapeBuffer for the database
MultiPartShapeBuffer polyline;
...
if (vCurves.size() != 0)
{
byte* curve;
polyline.GetCurves(curve);
for (vector<esriSegmentModifier>::const_iterator iter = vCurves.begin(); iter != vCurves.end(); ++iter)
{
// SegmentArc is the only curve supported by this code
assert(iter->segmentType == esriSegmentArc);
// copy the data from my vector to the ShapeBuffer
esriSegmentModifier* modifier = reinterpret_cast<esriSegmentModifier*>(curve);
*modifier = *iter;
curve += offsetof(esriSegmentModifier, segmentParams) + sizeof(SegmentArc);
}
}
polyline.CalculateExtent();
polyline.PackCurves();
row.SetGeometry(polyline);
}