The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specification. It is also defined in the ISO SQL/MM Part 3: Spatial standard.
WKB is used to exchange geometry data as binary streams
represented by BLOB
values
containing geometric WKB information.
WKB uses one-byte unsigned integers, four-byte unsigned integers, and eight-byte double-precision numbers (IEEE 754 format). A byte is eight bits.
For example, a WKB value that corresponds to POINT(1
1)
consists of this sequence of 21 bytes (each
represented here by two hex digits):
0101000000000000000000F03F000000000000F03F
The sequence may be broken down into these components:
Byte order : 01 WKB type : 01000000 X : 000000000000F03F Y : 000000000000F03F
Component representation is as follows:
The byte order may be either 1 or 0 to indicate little-endian or big-endian storage. The little-endian and big-endian byte orders are also known as Network Data Representation (NDR) and External Data Representation (XDR), respectively.
The WKB type is a code that indicates the geometry type.
Values from 1 through 7 indicate Point
,
LineString
, Polygon
,
MultiPoint
,
MultiLineString
,
MultiPolygon
, and
GeometryCollection
.
A Point
value has X and Y coordinates,
each represented as a double-precision value.
WKB values for more complex geometry values are represented by more complex data structures, as detailed in the OpenGIS specification.
User Comments
To parse a WKB point in PHP, use the unpack function. It's similar to Perl's except that each format string has a label, and is separated from the next by a slash. The result is an associative array using those labels:
<?php
// $wkb is the value retrieved from MySQL using AsBinary(g)
$geometry = unpack(corder/Ltype/dlatitude/dlongitude, $wkb);
if ($geometry['type'] == 1) {
$latitude = $geometry['latitude'];
$longitude = $geometry['longitude'];
}
?>
You can also unpack a polygon or a collection (e.g. Multipolygon) as follows:
<?php
//Step 1 - get number of elements
$query1 = "SELECT NumGeometries($geom)from ......" ;
$result1 = mysql_query($query1);
$row1 = mysql_fetch_row($result1);
$N = $row1[0]; //number of polygons in the Multipolygon
//Step 2 - loop through each polygon
$n=1;
while ($n<=$N){
$query = "SELECT AsBinary(GeometryN($geom,$n))from .....";
//returns a single POLYGON from a MULTIPOYGON
$result = mysql_query($query);
if($result){
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$geometry = unpack("corder/Ltype/d*", $row[0]);
$i=2;
while($i<count($geometry)){
echo $geometry[$i]."<br>";
$i++;
}
}
}
$n++;
}
?>
Hope it helps as it took me a little while to figure out how to extend the excellent unpack example given by Michael
Adding to the two other examples, here is how to parse a LINESTRING:
<?php
// $wkb is the value retrieved from MySQL using AsBinary(g)
$geometry = unpack(corder/Ltype/Llength/d*, $wkb);
if ($geometry['type'] == 2) {
for ($i = 1; $i < $geometry['length'] * 2; $i += 2) {
$latitude = $geometry[$i];
$longitude = $geometry[$i+1];
}
}
?>
Add your own comment.