It looks to me like there's a bug in IMSegmentation3.CalibrateByMs for v10.0 sp2. When I create a diagonal polyline from 0.0,0.0 to 10.0,10.0 with unknown measures at its vertices, then calibrate it, I would expect to see all vertices have measures - not just the ones inserted.
Update
Oops, I had forgot to call CalculateNonSimpleMs, after adding it, I get this output. I would expect to see a measure of 100.0 at 10.0,10.0 - not 62.5. I think this is a bug.
split 2.5,2.5,100.0
split 5.0,5.0,50.0
split 7.5,7.5,75.0
0.0,0.0,112.5 (BUG)
2.5,2.5,100.0
5.0,5.0,50.0
6.0,6.0,60.0 (CORRECT)
7.5,7.5,75.0
10.0,10.0,62.5 (BUG)
Measure at 0.55 is 55.00000001234
Here's the c# code:
public static void TestPolylineM(ISpatialReference sr)
{
var calibrationPts = new MultipointClass() as IPointCollection;
((IMAware)calibrationPts).MAware = true;
((IGeometry)calibrationPts).SpatialReference = sr;
// x y m
calibrationPts.AddPoint(MakePointM(2.5, 2.5, 100.0, sr));
calibrationPts.AddPoint(MakePointM(5.0, 5.0, 50.0, sr));
calibrationPts.AddPoint(MakePointM(7.5, 7.5, 75.0, sr));
IPointCollection pc = new PolylineClass();
((IGeometry)pc).SpatialReference = sr;
((IMAware)pc).MAware = true;
pc.AddPoint(MakePointM(0.0, 0.0, double.NaN, sr));
pc.AddPoint(MakePointM(6.0, 6.0, double.NaN, sr));
pc.AddPoint(MakePointM(10.0, 10.0, double.NaN, sr));
var mseg = pc as IMSegmentation3;
int how = (int) (esriGeometryUpdateMEnum.esriGeometryInterpolate
| esriGeometryUpdateMEnum.esriGeometryExtrapolateAfter
| esriGeometryUpdateMEnum.esriGeometryExtrapolateBefore);
Simplify((IGeometry)pc);
double cutoffDistance = 1.0;
var splitPoints = mseg.CalibrateByMs(calibrationPts.EnumVertices, how, cutoffDistance);
mseg.CalculateNonSimpleMs();
ListSplits(splitPoints);
for (int i = 0; i < pc.PointCount; i++)
{
var pnt = pc.get_Point(i);
Debug.Print("{0:0.0},{1:0.0},{2:0.0}", pnt.X, pnt.Y, pnt.M);
}
double distAlong = 0.55;
var measures = mseg.GetMsAtDistance(distAlong, true) as double[];
Debug.Print("Measure at {0} is {1}", distAlong, measures[0]);
}
public static IPoint MakePointM(double x, double y,double m, ISpatialReference sr)
{
IPoint pnt = new PointClass();
((IMAware)pnt).MAware = true;
pnt.SpatialReference = sr;
pnt.PutCoords(x, y);
if(!Double.IsNaN(m))
pnt.M = m;
return pnt;
}
public static void ListSplits(IEnumSplitPoint splitPoints)
{
IPoint splitPoint;
int partIndex;
int vertexIndex;
splitPoints.Next(out splitPoint, out partIndex, out vertexIndex);
while (splitPoint != null)
{
Debug.Print("split {0:0.0},{1:0.0},{2:0.0}", splitPoint.X, splitPoint.Y, splitPoint.M);
splitPoints.Next(out splitPoint, out partIndex, out vertexIndex);
}
}
public static void Simplify(IGeometry geom)
{
var topoOp = geom as ITopologicalOperator2;
if (topoOp != null)
{
topoOp.IsKnownSimple_2 = false;
topoOp.Simplify();
}
}