Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better all-round 3D support #53

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions geoPHP.inc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class geoPHP
$type_map = geoPHP::getAdapterMap();

// Auto-detect type if needed
if (!$type) {
if (!$type || $type == 'auto') {
// If the user is trying to load a Geometry from a Geometry... Just pass it back
if (is_object($data)) {
if ($data instanceOf Geometry) return $data;
Expand Down Expand Up @@ -220,7 +220,8 @@ class geoPHP

// 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));
$retry = ltrim($input);
return geoPHP::detectFormat($retry);
}

// Detect WKB or EWKB -- first byte is 1 (little endian indicator)
Expand Down
94 changes: 4 additions & 90 deletions lib/adapters/EWKB.class.php
Original file line number Diff line number Diff line change
@@ -1,96 +1,10 @@
<?php
/**
* EWKB (Extended Well Known Binary) Adapter
*
* @todo follow ewkt implementation
* ewkb http://svn.osgeo.org/postgis/trunk/doc/ZMSgeoms.txt
*/
class EWKB extends WKB
{

/**
* Read WKB binary string into geometry objects
*
* @param string $wkb An Extended-WKB binary string
*
* @return Geometry
*/
public function read($wkb, $is_hex_string = FALSE) {
if ($is_hex_string) {
$wkb = pack('H*',$wkb);
}

// Open the wkb up in memory so we can examine the SRID
$mem = fopen('php://memory', 'r+');
fwrite($mem, $wkb);
fseek($mem, 0);
$base_info = unpack("corder/ctype/cz/cm/cs", fread($mem, 5));
if ($base_info['s']) {
$srid = unpack("Lsrid", fread($mem, 4));
}
else {
$srid = NULL;
}
fclose($mem);

// Run the wkb through the normal WKB reader to get the geometry
$wkb_reader = new WKB();
$geom = $wkb_reader->read($wkb);

// If there is an SRID, add it to the geometry
if ($srid) {
$geom->setSRID($srid);
}

return $geom;
}

/**
* Serialize geometries into an EWKB binary string.
*
* @param Geometry $geometry
*
* @return string The Extended-WKB binary string representation of the input geometries
*/
public function write(Geometry $geometry, $write_as_hex = FALSE) {
// We always write into NDR (little endian)
$wkb = pack('c',1);

switch ($geometry->getGeomType()) {
case 'Point';
$wkb .= pack('L',1);
$wkb .= $this->writePoint($geometry);
break;
case 'LineString';
$wkb .= pack('L',2);
$wkb .= $this->writeLineString($geometry);
break;
case 'Polygon';
$wkb .= pack('L',3);
$wkb .= $this->writePolygon($geometry);
break;
case 'MultiPoint';
$wkb .= pack('L',4);
$wkb .= $this->writeMulti($geometry);
break;
case 'MultiLineString';
$wkb .= pack('L',5);
$wkb .= $this->writeMulti($geometry);
break;
case 'MultiPolygon';
$wkb .= pack('L',6);
$wkb .= $this->writeMulti($geometry);
break;
case 'GeometryCollection';
$wkb .= pack('L',7);
$wkb .= $this->writeMulti($geometry);
break;
}

if ($write_as_hex) {
$unpacked = unpack('H*',$wkb);
return $unpacked[1];
}
else {
return $wkb;
}
}

}
}
39 changes: 26 additions & 13 deletions lib/adapters/GPX.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

/**
* PHP Geometry/GPX encoder/decoder
* gpx spec: http://www.topografix.com/GPX/1/1/
*/
class GPX extends GeoAdapter
{
Expand Down Expand Up @@ -48,6 +49,8 @@ public function geomFromText($text) {
$text = preg_replace('/<!\[cdata\[(.*?)\]\]>/s','',$text);

// Load into DOMDocument
//ignore error
libxml_use_internal_errors(true);
$xmlobj = new DOMDocument();
@$xmlobj->loadXML($text);
if ($xmlobj === false) {
Expand Down Expand Up @@ -93,9 +96,7 @@ protected function parseWaypoints() {
$points = array();
$wpt_elements = $this->xmlobj->getElementsByTagName('wpt');
foreach ($wpt_elements as $wpt) {
$lat = $wpt->attributes->getNamedItem("lat")->nodeValue;
$lon = $wpt->attributes->getNamedItem("lon")->nodeValue;
$points[] = new Point($lon, $lat);
$points[] = $this->pointNode($wpt);
}
return $points;
}
Expand All @@ -107,9 +108,7 @@ protected function parseTracks() {
$components = array();
foreach ($this->childElements($trk, 'trkseg') as $trkseg) {
foreach ($this->childElements($trkseg, 'trkpt') as $trkpt) {
$lat = $trkpt->attributes->getNamedItem("lat")->nodeValue;
$lon = $trkpt->attributes->getNamedItem("lon")->nodeValue;
$components[] = new Point($lon, $lat);
$components[] = $this->pointNode($trkpt);
}
}
if ($components) {$lines[] = new LineString($components);}
Expand All @@ -123,9 +122,7 @@ protected function parseRoutes() {
foreach ($rte_elements as $rte) {
$components = array();
foreach ($this->childElements($rte, 'rtept') as $rtept) {
$lat = $rtept->attributes->getNamedItem("lat")->nodeValue;
$lon = $rtept->attributes->getNamedItem("lon")->nodeValue;
$components[] = new Point($lon, $lat);
$components[] = $this->pointNode($rtept);
}
$lines[] = new LineString($components);
}
Expand All @@ -151,15 +148,32 @@ protected function geometryToGPX($geom) {
}
}

private function pointToGPX($geom) {
return '<'.$this->nss.'wpt lat="'.$geom->getY().'" lon="'.$geom->getX().'" />';
protected function pointNode($node) {
$lat = $node->attributes->getNamedItem("lat")->nodeValue;
$lon = $node->attributes->getNamedItem("lon")->nodeValue;
$elevation = null;
$ele = $node->getElementsByTagName('ele');
if ( $ele->length ) {
$elevation = $ele->item(0)->nodeValue;
}
return new Point($lon, $lat, $elevation);
}

private function pointToGPX(Geometry $geom) {
if ( $geom->hasZ() ) {
$c = '<'.$this->nss.'wpt lat="'.$geom->getY().'" lon="'.$geom->getX().'">';
$c .= '<ele>'.$geom->z().'</ele>';
$c .= '</'.$this->nss.'wpt>';
return $c;
}
return '<'.$this->nss.'wpt lat="'.$geom->getY().'" lon="'.$geom->getX().'" />';
}

private function linestringToGPX($geom) {
$gpx = '<'.$this->nss.'trk><'.$this->nss.'trkseg>';

foreach ($geom->getComponents() as $comp) {
$gpx .= '<'.$this->nss.'trkpt lat="'.$comp->getY().'" lon="'.$comp->getX().'" />';
$gpx .= $this->pointToGPX($comp);
}

$gpx .= '</'.$this->nss.'trkseg></'.$this->nss.'trk>';
Expand All @@ -176,5 +190,4 @@ public function collectionToGPX($geom) {

return $gpx;
}

}
25 changes: 13 additions & 12 deletions lib/adapters/KML.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,14 @@ protected function parseLineString($xml) {
protected function parsePolygon($xml) {
$components = array();

$outer_boundary_element_a = $this->childElements($xml, 'outerboundaryis');
$outer_boundary_element = $outer_boundary_element_a[0];
$outer_ring_element_a = $this->childElements($outer_boundary_element, 'linearring');
$outer_ring_element = $outer_ring_element_a[0];
$components[] = $this->parseLineString($outer_ring_element);
if ( $outer_boundary_element_a = $this->childElements($xml, 'outerboundaryis') ) {
$outer_boundary_element = $outer_boundary_element_a[0];
$outer_ring_element_a = $this->childElements($outer_boundary_element, 'linearring');
$outer_ring_element = $outer_ring_element_a[0];
$components[] = $this->parseLineString($outer_ring_element);
}

if (count($components) != 1) {
if (count($components) != 1) {
throw new Exception("Invalid KML");
}

Expand Down Expand Up @@ -209,7 +210,7 @@ private function pointToKML($geom) {
return '<'.$this->nss.'Point><'.$this->nss.'coordinates>'.$geom->getX().",".$geom->getY().'</'.$this->nss.'coordinates></'.$this->nss.'Point>';
}

private function linestringToKML($geom, $type = FALSE) {
private function linestringToKML(LineString $geom, $type = FALSE) {
if (!$type) {
$type = $geom->getGeomType();
}
Expand All @@ -233,16 +234,16 @@ private function linestringToKML($geom, $type = FALSE) {
return $str;
}

public function polygonToKML($geom) {
public function polygonToKML(Polygon $geom) {
$components = $geom->getComponents();
if (!empty($components)) {
$str = '';
if ( count($components) ) {
$str = '<'.$this->nss.'outerBoundaryIs>' . $this->linestringToKML($components[0], 'LinearRing') . '</'.$this->nss.'outerBoundaryIs>';
foreach (array_slice($components, 1) as $comp) {
$str .= '<'.$this->nss.'innerBoundaryIs>' . $this->linestringToKML($comp) . '</'.$this->nss.'innerBoundaryIs>';
}
}

return '<'.$this->nss.'Polygon>'. $str .'</'.$this->nss.'Polygon>';
return '<'.$this->nss.'Polygon>'. $str .'</'.$this->nss.'Polygon>';
}
}

public function collectionToKML($geom) {
Expand Down
Loading