ArcObjects Library Reference (NetworkAnalyst)  

INACompactStreetDirection.CompressedGeometry Property

The compressed geometry for the driving direction.

[Visual Basic .NET]
Public ReadOnly Property CompressedGeometry As String
[C#]
public string CompressedGeometry {get;}
[C++]
HRESULT get_CompressedGeometry(
  BSTR* strGeometry
);
[C++]

Parameters

strGeometry [out, retval]   strGeometry is a parameter of type BSTR

Product Availability

Available with ArcGIS Engine, ArcGIS Desktop, and ArcGIS Server. Requires Network Analyst Extension.

Remarks

CompressedGeometry returns a compressed line geometry representing the direction.  By compressing the geometry, the overall size of the direction item is significantly reduced. 

The direction's line geometry is compressed by the directions agent.  It compresses it by converting the line geometry into a string that holds the relative offsets of the points in the line as integers stored in 32-based notation.

Here is a description of the compression algorithm that is used:

Input to compression: 
  dirPoints - Direction's line geometry as a collection of points
  coefficient - Integer to multiply each x and y double by when converting to integer
Output: 
  compressedGeometry - String representing geometry
1. Convert coefficient to string and add to the start of the compressedGeometry string
2. set pointPrev = (0,0)
3. For each point in dirPoints
   a. int xDifference = Round(coefficient  * (point.x - pointPrev.x))
   b. Int yDifference = Round(coefficient  * (point.y - pointPrev.y))
   c. Convert xDifference to string using 32-based scale and add to compressedGeometry string
   d. Convert yDifference to string using 32-based scale and add to compressedGeometry string
   e. pointPrev = point;
4. return compressedGeometry string

To extract the points for the line geometry from the CompressedGeometry string, the reverse of the above must be done.  It is necessary to get the first integer from the string and convert it to an integer to be used as the coefficient.  Then, pop off each remaining substring and convert it back into a double.

Here is a description of the uncompression algorithm:

Input to decompression: 
  compressedGeometry - String representing geometry
Output:
  dirPoints - Direction's line geometry as a collection of points 
1. get first token from compressedGeometry string and convert to integer to use as the coefficient
2. xDiffPrev = 0, yDiffPrev = 0
3. For each point in dirPoints
   a. xDiff = get token from compressedGeometry string and convert from 32-based scale to integer
   b. yDiff = get token from compressedGeometry string and convert from 32-based scale to integer
   c. point.x = (xDiff + xDiffPrev) / coefficient
   e. point.y = (yDiff + yDiffPrev) / coeffiecint
   f. add point to dirPoints
   g. xDiffPrev = xDiff, yDiffPrev = yDiff
4. return dirPoints

Thus, with the following input data:
dirPoints:
  -118.356654545455, 34.1146
  -118.356436363636, 34.1143272727273
  -118.356418181818, 34.1142363636364
  -118.356490909091, 34.1137636363636
coefficient:
  55000 - represents 2 meter resolution

It would be compressed into the following string:
"+1lmo-66l1f+1p8af+c-f+1-5-4-q"

When uncompressed, the resulting points would be the following (slightly different due to lossy compression): 
  -118.356636363636, 34.1146
  -118.356418181818, 34.1143272727273
  -118.3564, 34.1142363636364
  -118.356472727273, 34.1137636363636

[C#]

Below is some sample code that will decompress a CompressedGeometry into an array of XY.

   
    private struct XY
    {
      public double x;
      public double y;
    }
    private char[] m_abc = {'0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j',
            'k','l','m','n','o','p','q','r','s','t','u','v'};
    private XY[] ExtractPointsFromCompressedGeometry(System.String compresedGeometry)
    {
      // initialize result storage
      System.Collections.Generic.List< XY > result = new System.Collections.Generic.List< XY >(); // memory exception
      int nIndex = 0;
      double dMultBy = (double)ExtractInt(compresedGeometry, ref nIndex); // exception
      int nLastDiffX = 0;
      int nLastDiffY = 0;
      int nLength = compresedGeometry.Length; // reduce call stack
      while (nIndex != nLength)
      {
        // extract number
        int nDiffX = ExtractInt(compresedGeometry, ref nIndex); // exception
        int nDiffY = ExtractInt(compresedGeometry, ref nIndex); // exception
        // decompress
        int nX = nDiffX + nLastDiffX;
        int nY = nDiffY + nLastDiffY;
        double dX = (double)nX / dMultBy;
        double dY = (double)nY / dMultBy;
        // add result item
        XY point = new XY();
        point.x = dX;
        point.y = dY;
        result.Add(point); // memory exception
        // prepare for next calculation
        nLastDiffX = nX;
        nLastDiffY = nY;
      }
      // return result
      return result.ToArray();
    }
    // Read one integer from compressed geometry string by using passed position
    // Returns extracted integer, and re-writes nStartPos for the next integer
    private int ExtractInt(string src, ref int nStartPos) // exception
    {
      bool bStop = false;
      System.Text.StringBuilder result = new System.Text.StringBuilder();
      int nCurrentPos = nStartPos;
      while (!bStop)
      {
        char cCurrent = src[nCurrentPos];
        if (cCurrent == '+' || cCurrent == '-')
        {
          if (nCurrentPos != nStartPos)
          {
            bStop = true;
            continue;
          }
        }
        result.Append(cCurrent); // exception
        nCurrentPos++;
        if (nCurrentPos == src.Length) // check overflow
          bStop = true;
      }
      int nResult = int.MinValue;
      if (result.Length != 0)
      {
        nResult = FromStringRadix32(result.ToString());
        nStartPos = nCurrentPos;
      }
      return nResult;
    }
    // Sample input and output: +1lmo -> 55000
    private int FromStringRadix32(string s) // exception
    {
      int result = 0;
      for (int i = 1; i < s.Length; i++)
      {
        char cur = s[i];
        System.Diagnostics.Debug.Assert((cur >= '0' && cur <= '9') || (cur >= 'a' && cur <= 'v'));
        if (cur >= '0' && cur <= '9')
          result = (result << 5) + System.Convert.ToInt32(cur) - System.Convert.ToInt32('0');
        else if (cur >= 'a' && cur <= 'v')
          result = (result << 5) + System.Convert.ToInt32(cur) - System.Convert.ToInt32('a') + 10;
        else throw new System.ArgumentOutOfRangeException(); // exception
      }
      if (s[0] == '-')
        result = -result;
      else if (s[0] != '+')
        throw new System.ArgumentOutOfRangeException(); // exception
      return result;
    }

See Also

INACompactStreetDirection Interface