This document is archived and information here might be outdated. Recommended version. |
ArcObjects namespaces > NetworkAnalyst > ESRI.ArcGIS.NetworkAnalyst > Interfaces > IN > INACompactStreetDirection Interface > INACompactStreetDirection.CompressedGeometry Property (ArcObjects .NET 10.4 SDK) |
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
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
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;
}