What's the format of the Shape column blob in a mobile geodatabase?

2522
11
12-21-2020 02:10 PM
KirkKuykendall1
Occasional Contributor III

Hi -

With 2.7, I created a mobile geodatabase with a simple webmercator polygon featureclass in it.

Using Microsoft.Data.Sqlite, I'm able to read the byte array, but both GeometryEngine.ImportFromEsriShape and ImportFromWKB throw an exception.

Anyone know what the format of the byte array is?

Thanks, Kirk

Tags (1)
0 Kudos
11 Replies
JoshuaBixby
MVP Esteemed Contributor

For those wondering why the OP is using Pro SDK and not just reading the mobile geodatabase directly:  How to open a Mobile Geodatabase? - GeoNet, The Esri Community

The Pro SDK doesn't yet support directly opening mobile geodatabases.
0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

I don't have a sample to read the blob data from a Mobile Geodatabase but I have a snippet that reads the blob data from a Personal Geodatabase.   It's been a while since i worked with Mobile data and i am not sure if the format is the same,  But if you try this you will need the blob buffer and the spatial reference to get the Geometry back:

private static Geometry GetGeometryFromBuffer(byte[] geomBuffer, SpatialReference sr)
{
  var geomType = GetGeometryType(geomBuffer);
  switch (geomType)
  {
    case GeometryType.Point:
      {
        var mp = MapPointBuilder.FromEsriShape(geomBuffer, sr);
        //System.Diagnostics.Debug.WriteLine($@"x: {x} = {mp.X} y: {y} = {mp.Y}");
        return mp;
      }
    case GeometryType.Polyline:
      {
        var line = PolylineBuilder.FromEsriShape(geomBuffer, sr);
        return line;
      }

    case GeometryType.Polygon:
      {
        var poly = PolygonBuilder.FromEsriShape(geomBuffer, sr);
        return poly;
      }
  }
  return null;
}

private static GeometryType GetGeometryType(byte[] buffer, int offset = 0)
{
  // read the shape type            
  int typeInt = BitConverter.ToInt32(buffer, offset);
  int type = (int)(typeInt & (int)0x000000FF);
  switch (type)
  {
    case 0:
      return GeometryType.Unknown;
    case 1:
    // A point consists of a pair of double-precision coordinates.
    case 21:
    // A PointM consists of a pair of double-precision coordinates       
    // in the order X, Y, plus a measure M.
    case 11:
    // A PointZM consists of a triplet of double-precision coordinates plus a measure.
    case 9:
      // A PointZ consists of a triplet of double-precision coordinates in the order X, Y, Z
      // where Z usually represents height.
      return GeometryType.Point;
    case 3:
    // PolyLine is an ordered set of vertices that consists of one or more parts.
    // A part is a connected sequence of two or more points. Parts may or may not
    // be connected to one another. Parts may or may not intersect one another.
    case 23:
    // A shapefile PolyLineM consists of one or more parts. A part is a connected
    // sequence of two or more points. Parts may or may not be connected to one 
    // another. Parts may or may not intersect one another.
    case 13:
    // A shapefile PolyLineZM consists of one or more parts. A part is a
    // connected sequence of two or more points. Parts may or may not be connected 
    // to one another. Parts may or may not intersect one another.
    case 10:
      // A PolyLineZ consists of one or more parts. A part is a connected
      // sequence of two or more points. Parts may or may not be connected
      // to one another. Parts may or may not intersect one another.
      return GeometryType.Polyline;
    case 5:
    // A polygon consists of one or more rings. A ring is a connected sequence
    // of four or more points that form a closed, non-self-intersecting loop. 
    // A polygon may contain multiple outer rings. The order of vertices or 
    // orientation for a ring indicates which side of the ring is the interior of 
    // the polygon. The neighborhood to the right of an observer walking along
    // the ring in vertex order is the neighborhood inside the polygon. Vertices
    // of rings defining holes in polygons are in a counterclockwise direction.
    // Vertices for a single, ringed polygon are, therefore, always in clockwise
    // order. The rings of a polygon are referred to as its parts.
    case 25:
    // A PolygonM consists of a number of rings. A ring is a closed, non-self-intersecting loop.
    case 15:
    // A PolygonZM consists of a number of rings. A ring is a closed, non-self-intersecting loop.
    case 19:
      // A PolygonZ consists of a number of rings. A ring is a closed, non-self-intersecting loop.
      // A PolygonZ may contain multiple outer rings. The rings of a PolygonZ are referred to as
      // its parts.
      return GeometryType.Polygon;
    case 50:
      // GeneralPolyline
      return GeometryType.Polyline;
    case 51:
      //   GeneralPolygon 
      return GeometryType.Polygon;
    case 52:
      //  GeneralPoint
      return GeometryType.Point;
    // not supported: 31: MultiPatchM
    // not supported: 32: MultiPatch
    // not supported: 53: GeneralMultiPoint
    // not supported: 54: GeneralMultiPatch
    default:
      throw new Exception($@"Unknown shape type {type}");
  }
}

 

KirkKuykendall1
Occasional Contributor III

Hi Wolf -

I get a shapetype of 100, throwing "unknow shape type" for both my polygon featureclass as well as a point featureclass.

I'll hold off on this til it's supported via CoreHost or .NET runtime SDK.

If the geodatabase is intended to make it easier for 3rd party devs, it would be nice to have this documented so apps can read it with no Esri dependencies.

Thanks, Kirk

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

What, actually publish a specification?  Dare to dream @KirkKuykendall1😊

0 Kudos
KirkKuykendall1
Occasional Contributor III

At first glance it looks like Spatialite is to Sqlite what PostGIS is to PostgreSql (?)

Esri supports spatial in PostGreSql but doesn't require installing PostGIS, which has ST_Geometry.

The attribute table for sqlite looks St_Geometry based:

mypolygons1.PNG

Esri has good documentation for Adding the ST_Geometry type to a PostgreSQL database .   Hopefully documentation of that caliber is in the works for Sqlite. 

 

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

I am using ArcGIS Pro 2.7, created a Mobile SQLite database (using the GP Tool), and copied some point data into a SQLite feature class.  I was able to read/write data to/from that SQLite database by just accessing it via the Geodatabase API.  I haven't tried to access the data via a CoreHost app yet, but i think that should work as well, so i am not sure why you need to hold off until it is supported.  Can you explain your use case that requires you to read the data via Microsoft.Data.Sqlite? 

Below is a screenshot of 2.7 showing Points from a SQLite database.

SQLite.png

0 Kudos
KirkKuykendall1
Occasional Contributor III

Hi Wolf -

Years ago I developed a windows-based mobile app with ArcEngine.  This was for an organization that mostly runs linux based apps.  At the time they expressed an interest in having something more open than a file geodatabase.  As ArcEngine approaches end-of-life, they'll need to re-write it.  When that day comes I'd like to present Sqlite geodatabase as a storage option, and explain how their other apps can read the spatial data in it (with no Esri dependencies).  

See Rich's response on issues about opening .geodatabase with CoreHost.

Side note - it seems like Esri could re-compile the CoreHost assemblies targeting .NET 5.0 and provide as a separate product.  That way it could run on linux (right?)

Thanks, Kirk

 

0 Kudos
KirkKuykendall1
Occasional Contributor III

Found more info here:

"Esri has implemented an ST_Geometry type in Oracle, PostgreSQL, and SQLite. It is this ST_Geometry data type that is explained in the ArcGIS help."

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Ok, i understand now.  I don't think that CoreHost is what you looking for.  CoreHost requires a valid Pro license and making it run on Linux is not as easy as one might think because CoreHost only represents the client-side for an underlying service infrastructure that actually performs all the work.  So the whole stack client/services would have to be ported to run on Linux.  As for using a SQLite mobile Geodatabase, i would not really consider this to be an 'open' platform because only the physical access to data is 'open' (meaning that access is available on Windows, Linux, etc), on the logical access level the internal data and metadata formats of a GeoDatabase are not a published as an open standard (like for example the shape file format). 

Depending on your use case you could consider the Pro Plugin Datasource  this would allow you to access features and rows in any kind of format from within ArcGIS Pro.  Pro Plugins allow access to spatial and non-spatial data stored in files or databases, but Pro Plugins can only read and display the data (no writes) in Pro.  By using a Pro Plugin you could use a SQLite database that is authored on Linux, write your spatial and non-spatial data into table (using any format) and then use a Pro Plugin Datasource to allow 'seamless' read-only access to that data.  If your use case requires the data to be authored on ArcGIS Pro and 'read' or 'written' on Linux i would consider to use shape files.

0 Kudos