Update on SqlGeometry and POINT EMPTY in WKB

Long time ago I discussed about how SqlGeometry handles POINT EMPTY in WKB format. The SqlGeometry states the definition of OGC GEOMETRY type for Microsoft SQL Server. Shortly, the message was that SqlGeometry implicitly casts POINT EMPTY to MULTIPOINT EMPTY geometry when generating WKB output. PostGIS casts as well, but does it in a consistent way, in my opinion, outputting GEOMETRYCOLLECTION.

Following those findings, I assumed it is not quite correct, or I didn’t like the inconsistency, and I had reported it to Microsoft Connect as a bug: SqlGeometry reports invalid type of WKB of POINT EMPTY.

Recently, I have received a couple of comments from Microsoft to my report. The comments are attached to the report linked above, but I paste them below for completeness and archive:

Our development team for the spatial data types tells me that it is not possible to use a single value for the WKB format of any spatial data type. For the POINT EMPTY, the WKB format does not allow empty points, so we are outputting a MULTIPOINT with zero elements.
In a MULTIPOINT EMPTY, we are stripping out empty points.

The reasoning is technically correct. It’s just Microsoft does it differently. However, as second comment suggests, the current behaviour may change in future:

But we might consider changing it to get consistent behavior.

WKB hex decoder in C++

In PostGIS world, I often need to construct geometry from Well-Known-Binary (WKB) or PostGIS EWKB stream encoded as hex stream. It’s easy to do if I have access to PostgreSQL/PostGIS client which accepts SQL queries:

SELECT
   ST_AsText(
      ST_GeomFromWKB(
         decode('0101000000e5d022dbf93e2e40dbf97e6abc743540', 'hex'),
         4326))

I often need to do the same directly in C++ code – parse hex encoded binary stream to raw stream of bytes. Here is simple hex decoder I use:

#include <sstream>
#include <string>
#include <vector>
typedef std::vector<unsigned char> ewkb_t;

// bytes [out] - buffer for binary output
void hex_to_bytes(std::string const& hexstr, ewkb_t& bytes)
{
    bytes.clear();
    for(std::string::size_type i = 0; i < hexstr.size() / 2; ++i)
    {
        std::istringstream iss(hexstr.substr(i * 2, 2));
        unsigned int n;
        iss >> std::hex >> n;
        bytes.push_back(static_cast<unsigned char>(n));
    }
}

For example, I use it to build FDO geometry objects using another utility CreateGeometryFromExtendedWkb defined in FDO provider for PostGIS:

// POINT (1.234 5.678)
std::string ewkbhex("01010000005839B4C876BEF33F83C0CAA145B61640");
ewkb_t ewkb;
hex_to_bytes(ewkbhex, ewkb);
if (!ewkb.empty())
{
   FdoPtr<fdoigeometry> g = CreateGeometryFromExtendedWkb(ewkb);
   // ... use geometry
}