/** * Convert a raw coverage value to WKT. * * @param string $coverage The raw coverage. * @return string|null The WKT. */ function nl_extractWkt($coverage) { $wkt = null; // Get coverage format. $format = geoPHP::detectFormat($coverage); // Convert / reduce to WKT. if (in_array($format, array('wkt', 'kml'))) { $wkt = geoPHP::load($coverage)->out('wkt'); } return $wkt; }
/** * Return record coverage data from the NeatlineFeatures plugin. * * @param $record NeatlineRecord The record to get the feature for. * @return string|null */ function nl_getNeatlineFeaturesWkt($record) { // Halt if Features is not present. if (!plugin_is_active('NeatlineFeatures')) { return; } $db = get_db(); // Get raw coverage. $result = $db->fetchOne("SELECT geo FROM `{$db->prefix}neatline_features`\n WHERE is_map=1 AND item_id=?;", $record->item_id); if ($result) { // If KML, convert to WKT. if (geoPHP::detectFormat($result) == 'kml') { $result = nl_kml2wkt(trim($result)); } else { $result = 'GEOMETRYCOLLECTION(' . implode(',', explode('|', $result)) . ')'; } } return $result; }
static function detectFormat(&$input) { $mem = fopen('php://memory', 'r+'); fwrite($mem, $input, 11); // Write 11 bytes - we can detect the vast majority of formats in the first 11 bytes fseek($mem, 0); $bytes = unpack("c*", fread($mem, 11)); // If bytes is empty, then we were passed empty input if (empty($bytes)) { return FALSE; } // First char is a tab, space or carriage-return. trim it and try again if ($bytes[1] == 9 || $bytes[1] == 10 || $bytes[1] == 32) { return geoPHP::detectFormat(ltrim($input)); } // Detect WKB or EWKB -- first byte is 1 (little endian indicator) if ($bytes[1] == 1) { // If SRID byte is TRUE (1), it's EWKB if ($bytes[5]) { return 'ewkb'; } else { return 'wkb'; } } // Detect HEX encoded WKB or EWKB (PostGIS format) -- first byte is 48, second byte is 49 (hex '01' => first-byte = 1) if ($bytes[1] == 48 && $bytes[2] == 49) { // The shortest possible WKB string (LINESTRING EMPTY) is 18 hex-chars (9 encoded bytes) long // This differentiates it from a geohash, which is always shorter than 18 characters. if (strlen($input) >= 18) { //@@TODO: Differentiate between EWKB and WKB -- check hex-char 10 or 11 (SRID bool indicator at encoded byte 5) return 'ewkb:1'; } } // Detect GeoJSON - first char starts with { if ($bytes[1] == 123) { return 'json'; } // Detect EWKT - first char is S if ($bytes[1] == 83) { return 'ewkt'; } // Detect WKT - first char starts with P (80), L (76), M (77), or G (71) $wkt_chars = array(80, 76, 77, 71); if (in_array($bytes[1], $wkt_chars)) { return 'wkt'; } // Detect XML -- first char is < if ($bytes[1] == 60) { // grab the first 256 characters $string = substr($input, 0, 256); if (strpos($string, '<kml') !== FALSE) { return 'kml'; } if (strpos($string, '<coordinate') !== FALSE) { return 'kml'; } if (strpos($string, '<gpx') !== FALSE) { return 'gpx'; } if (strpos($string, '<georss') !== FALSE) { return 'georss'; } if (strpos($string, '<rss') !== FALSE) { return 'georss'; } if (strpos($string, '<feed') !== FALSE) { return 'georss'; } } // We need an 8 byte string for geohash and unpacked WKB / WKT fseek($mem, 0); $string = trim(fread($mem, 8)); // Detect geohash - geohash ONLY contains lowercase chars and numerics preg_match('/[a-z0-9]+/', $string, $matches); if ($matches[0] == $string) { return 'geohash'; } // What do you get when you cross an elephant with a rhino? // http://youtu.be/RCBn5J83Poc return FALSE; }
function test_detection($value, $format, $file) { $detected = geoPHP::detectFormat($value); if ($detected != $format) { if ($detected) { print 'detected as ' . $detected . "\n"; } else { print "format not detected\n"; } } // Make sure it loads using auto-detect geoPHP::load($value); }