Select to view content in your preferred language

MultiPartShapeBuffer::GetMs appears to return the wrong pointer value

3519
3
08-19-2012 06:37 PM
__11
by
Deactivated User
I'm having problems setting M values in a shapePolylineZM, and I suspect that the problem is that MultiPartShapeBuffer::GetMs() returns the wrong pointer value.

Here's the relevant section of my code that creates and writes the shape:

  struct pointInfo
  {
   pointInfo(double _easting, double _northing, double _height, double _shotPoint) 
   : easting(_easting), northing(_northing), height(_height), shotPoint(_shotPoint)
   {
   }
   double easting, northing, height, shotPoint;
  };
  vector<pointInfo> vPoints; // uses grid coordinates

  // ... add elements to vPoints, here ...

  // Now create and populate the geometry
  MultiPartShapeBuffer polyline;
  polyline.Setup(shapePolylineZM, 1 /*part*/, vPoints.size());

  Point* point;
  polyline.GetPoints(point);

  double* z;
  polyline.GetZs(z);

  double* m;
  polyline.GetMs(m);

  for (vector<pointInfo>::const_iterator iter = vPoints.begin(); iter != vPoints.end(); ++iter)
  {
   *z = iter->height;
   runParameters.geo->SetPointFromGrid(
    point++, 
    runParameters.geo->MetersToDest(iter->easting), 
    runParameters.geo->MetersToDest(iter->northing),
    z++);
   *m++ = iter->shotPoint;
  }

  polyline.CalculateExtent();
  row.SetGeometry(polyline);


I run this code then inspect the output by:
- load the geodatabase in ArcCatalog
- drag the feature class into ArcMap
- edit the feature ("Sketch Properties") to see the M values

I find that the M values are all in the wrong positions, offset by two.  Eg given input data x, y, z, m of
449419.597, 7772022.067, -104.192, 6459.000
449392.902, 7772057.754,  -97.530, 6460.000
449364.398, 7772096.582, -109.500, 6461.000
449342.910, 7772129.191, -105.321, 6462.000
...
410753.369, 7830191.197  -238.440, 7864.000
410726.857, 7830233.149, -245.280, 7865.000
410701.461, 7830273.902, -250.414, 7866.000
410673.267, 7830313.504, -242.441, 7867.000


I get these x, y, z, m values in the output
449419.597, 7772022.067, -104.192, 6461.000
449392.902, 7772057.754,  -97.530, 6462.000
449364.398, 7772096.582, -109.500, ...
449342.910, 7772129.191, -105.321, ...
...
410753.369, 7830191.197  -238.440, 7866.000
410726.857, 7830233.149, -245.280, 7867.000
410701.461, 7830273.902, -250.414, 0.000
410673.267, 7830313.504, -242.441, 0.000


A similar discrepancy occurs when I read a geometry. Eg I create a new geodatabase and feature class in ArcCatalog, then use ArcMap's editor to insert a row with x, y, z, m:
72.000, 38.518, 180.000, 41.000
74.328, 38.153, 181.000, 42.000
75.982, 35.619, 182.000, 43.000
78.201, 32.217, 183.000, 44.000
78.930, 30.795, 160.000, 45.000
80.105, 28.504, 161.000, 26.000
81.176, 26.415, 162.000, 27.000
83.455, 21.225, 163.000, 28.000
80.018, 15.917, 164.000, 29.000
84.599, 15.960, 165.000, 30.000


Then I use this code to read the geometry
 
 MultiPartShapeBuffer polyline;
 row.GetGeometry(polyline);

 ShapeType st;
 polyline.GetShapeType(st);
 assert(st == shapePolylineZM);

 int numPoints;
 polyline.GetNumPoints(numPoints);

 Point* p;
 polyline.GetPoints(p);

 double* m;
 polyline.GetMs(m);

 for (int i = 0; i < numPoints; ++i)
 {
  wcout << p.x << "\t" << p.y << "\t" << m << endl;
 }


and I get this result:

72      38.5182 26
74.328  38.1528 45
75.9815 35.6188 41
78.2013 32.217  42
78.9303 30.7952 43
80.105  28.5039 44
81.1763 26.4145 45
83.4546 21.2247 26
80.0181 15.9173 27
84.5989 15.9598 28

again the M values are in the wrong postion, offset by 2

It looks to me as if GetMs is returning the wrong value. In fact if I do this (after the code above):
 double *mExtent;
 err = polyline.GetMExtent(mExtent);
 wcout << "pointers: " << m << ", " << mExtent << ", " << m - mExtent << endl;


I can see that GetMExtent and GetMs return the same value, whereas I expected m to be 2*sizeof(double) higher than mExtent, in accordance with the structure described in Extended Shapefile Record Format, M data section, which shows MMin and MMax before Ms.

If I increment the pointer returned by GetMs by two, eg by using this class:
 class MultiPartShapeBuffer_fix : public FileGDBAPI::MultiPartShapeBuffer
 {
 public:
  fgdbError GetMs(double*& mArray) const
  { 
   fgdbError err = MultiPartShapeBuffer::GetMs(mArray);
   if (SUCCEEDED(err))
   {
    mArray += 2;
   }
   return err;
  }
 };

 MultiPartShapeBuffer_fix polyline;
 ...

My code appears to work properly, both reading and writing the geometry.

The problem appears in both v1.1 and 1.2 of FileGDB API.
It doesn't affect Z, only M.
I haven't tried other shapes, eg shapeGeneralPolyline

So....

Am I doing something wrong, or is there a bug in the API library?

If the library is correct, what am I doing wrong?

If the library has a bug, does it affect other shapes? I'm particularly interested in:
 MultiPartShapeBuffer polyline;
 polyline.Setup(static_cast<ShapeType>(shapeGeneralPolyline | shapeHasZs | shapeHasMs | shapeHasCurves), ...);

because I have code that uses it, and I need to know whether my fix applies to all shapes or only some.
0 Kudos
3 Replies
__11
by
Deactivated User
A quick test with
 MultiPartShapeBuffer polyline;
 polyline.Setup(static_cast<ShapeType>(shapeGeneralPolyline | shapeHasZs | shapeHasMs | shapeHasCurves), ... );

 ...

 double* m;
 polyline.GetMs(m);

Shows the same problem. The same fix (MultiPartShapeBuffer_fix) seems to fix the problem (tested with writing the geometry, but not reading an existing one).
0 Kudos
DavidSousa
Occasional Contributor
I examined the code and found that there is a bug. 

A fix will be included as part of the next bug fix release that will ship soon.  In the meantime, you can add an offset of 16 bytes to the pointer returned by GetMs.
0 Kudos
__11
by
Deactivated User
A fix will be included as part of the next bug fix release that will ship soon.


Thanks for that. Do we have a more specific time frame than "soon". I don't need an actual date, but it would be helpful to know whether it is days, weeks or months away.
0 Kudos