Location: PHPKode > projects > AppForMap > appformap/libs/phpgeometry_class.php
<?
/**
* This notice must be untouched at all times.
*
* The latest version is available at
* http://sourceforge.net/projects/appformap/
* @copyright Martin Høgh. All rights reserved.
* @author Martin Høgh <hide@address.com>
* @version 0.6
* @package phpgeometry_class.php
* @abstract Php class library. Creates geometry object from Well-known Text Representation or gml.
* The class's have operations for manipulating the geometry and getting various types of information.
*/
class geometryfactory
{
	/**
	* @return Geometry object
	* @param string $wkt test
	* @param int $srid
	* @desc Creates a new geometry object from a wkt string
	*/
	function createGeometry($wkt,$srid=NULL)//creates a new geometry object. Factory function
	{
		$wkt = str_replace(", ",",",$wkt);// replace " ," with ","
		preg_match_all("/[a-z]*[A-Z]*/",$wkt,$__typeArray);//Match the type of the geometry
		$__type=$__typeArray[0][0];
		switch ($__type)
		{
			case "MULTIPOLYGON":
			$geometryObject=new multipolygon($wkt,$srid);
			break;
			case "MULTILINESTRING":
			$geometryObject=new multilinestring($wkt,$srid);
			break;
			case "MULTIPOINT":
			$geometryObject=new multipoint($wkt,$srid);
			break;
			case "POINT":
			$geometryObject=new _point($wkt,$srid); //point is a key word
			break;
			case "LINESTRING":
			$geometryObject=new linestring($wkt,$srid);
			break;
			case "POLYGON":
			$geometryObject=new polygon($wkt,$srid);
			break;
		}
		return ($geometryObject);
	}
	function createGeometryCollection($wktArray)
	{
		$geometryCollection=new geometryCollection($wktArray);
		return($geometryCollection);
	}
	function deconstructionOfWKT() // Take a WKT string and returns a array with coords(string) for shapes. Called from a child object
	{
		preg_match_all("/[^a-z|(*]*[0-9]/",$this->wkt,$__wktArray); // regex is used exstract coordinates
		$wktArray=$__wktArray[0];
		if ($this->getGeomType()=="MULTIPOLYGON" || $this->getGeomType()=="POLYGON")
		{
			preg_match_all("/[^a-z|)]*[0-9]/",$this->wkt,$__array); // regex is used to find island shapes
			for ($__i = 0; $__i < (sizeof($__array[0])); $__i ++)
			{
				if (substr($__array[0][$__i], 0 ,2 )==",(" && substr($__array[0][$__i], 2 ,1 )!="(" )
				{
					$this->isIsland[$__i]=true;
				}
				else
				{
					$this->isIsland[$__i]=false;
				}
			}
		}
		if ($this->getGeomType()=="MULTIPOINT")// if multipoint when split the string again
		{
			preg_match_all("/[^a-z|,]*[0-9]/",$wktArray[0],$__array); // regex is used exstract coordinates
			$wktArray=$__array[0];
		}
		return ($wktArray);
	}
	function snapCoords($coordStr,$snapTolerance,$snapLayerStr,$shapeArray=array())
	{
		$__snap=false;
		$__newCoordStr = explode(",", $coordStr);
		$__snapLayerArray = explode(",", $snapLayerStr);
		$i = 0;
		foreach($__newCoordStr as $__v)// each point from the coordStr string is looped
		{
			$__snapToleranceTmp=$snapTolerance;// asign the value to a tmp var, so it can be restored
			$__oneCoord = explode(" ", $__v);
			$__oneCoordTmp = explode(" ", $__v);// save the original coord in a tmp for line snap
			$u = 0;
			// first check for vertex snap
			if (sizeof($__snapLayerArray))
			{
				foreach($__snapLayerArray as $__u)// each possible pointsnap point is evaluated
				{
					$__snapLayerCoord = explode(" ", $__u);
					$diffX = $__snapLayerCoord[0] - $__oneCoord[0];
					$diffY = $__snapLayerCoord[1] - $__oneCoord[1];
					$diff = sqrt(pow($diffX, 2) + pow($diffY, 2));
					//calculation of distance between the two point
					if ($diff <= $__snapToleranceTmp)// true if in snap tolerance
					{
						//echo "snap"."<br>";
						$__snapToleranceTmp = $diff;
						//decrease of snap tolerance, so only the nearest point is used
						$__snap = true; // point is snapped
						$__newSnapLayerCoord[0] = $__snapLayerCoord[0];
						$__newSnapLayerCoord[1] = $__snapLayerCoord[1];
					}
				}
			}
			if ($__snap == true) //true if evaluated point is snapped
			{
				$__oneCoord[0] = $__newSnapLayerCoord[0];
				//New value of digi point
				$__oneCoord[1] = $__newSnapLayerCoord[1];
				$__snap = false; // so the next digi point is not snapped
			}
			// second check for line snap
			if (sizeof($shapeArray))
			{
				foreach($shapeArray as $__u)// each possible line snap is evaluated
				{
					//echo "<script>alert('$__u');</script>";
					$__lineSegments = explode(",", $__u);
					for ($__i = 0; $__i < (sizeof($__lineSegments)-1); $__i ++)
					{
						$__l1=explode(" ",$__lineSegments[$__i]);// first coord in line segment
						$__l2=explode(" ",$__lineSegments[$__i+1]);// second coord in line segment
						$diff=$this->distancePointToLine ($__oneCoordTmp,$__l1,$__l2);
						//echo "<script>alert('tmp ".$__snapToleranceTmp."');</script>";
						//echo "<script>alert('lineafstand ".$diff[0]."');</script>";
						if ($diff[0] < $__snapToleranceTmp && $diff[0]!=FALSE)// true if in snap tolerance
						{
							//echo "<script>alert('".$diff[0]."');</script>"."<br>";
							$__snapToleranceTmp = $diff[0];
							//decrease of snap tolerance, so only the nearest point is used
							$__snap = true; // point is snapped
							$newCoord=$diff[1];
							$__newSnapLayerCoord[0] = $newCoord[0];
							$__newSnapLayerCoord[1] = $newCoord[1];
						}
					}
				}
				if ($__snap == true) //true if evaluated point is snapped
				{
					$__oneCoord[0] = $__newSnapLayerCoord[0];
					//New value of digi point
					$__oneCoord[1] = $__newSnapLayerCoord[1];
					$__snap = false; // so the next digi point is not snapped
				}
			}
			$__newCoordStr[$i] = implode(" ", $__oneCoord);
			$i ++;
		}
		$coordStr = implode(",", $__newCoordStr);
		return ($coordStr);
	}
	function getVertices()//get a string with all vertices of geometry
	{
		$verticeStr="";
		foreach($this->shapeArray as $__value)
		{
			$verticeStr=$verticeStr.$__value.",";
		}
		// remove the last comma
		$verticeStr=substr($verticeStr, 0, strlen($verticeStr) - 1);
		return($verticeStr);
	}
	function updateShape($coorStr,$shapeId)// updates the geometry on shape level. Takes a string with coords and a shape id
	{
		for ($__i = 0; $__i < sizeof($this->shapeArray); $__i ++)
		{
			if ($__i == $shapeId) {$this->shapeArray[$__i] = $coorStr;$__check=true;}
		}
		//echo "<script>alert(\"".$coorStr."\")</script>";
		if (!$__check) {$this->shapeArray[$this->getNumOfShapes()] = $coorStr;}
		$this->construction();
	}
	function snapShape($shapeId,$snapTolerance,$snapLayerStr,$shapeArray=array())// snaps one shape with shapeId of multifeature
	{
		$__newShape=$this->snapCoords($this->shapeArray[$shapeId],$snapTolerance,$snapLayerStr,$shapeArray);
		$this->updateShape($__newShape,$shapeId);
	}
	function snapAllShapes($snapTolerance,$snapLayerStr,$shapeArray=array())// snaps all shapes of multifeature or just like snap the hole geometry
	{
		foreach($this->shapeArray as $__key => $__shape)
		{
			$__newShape=$this->snapCoords($this->shapeArray[$__key],$snapTolerance,$snapLayerStr,$shapeArray);
			$this->updateShape($__newShape,$__key);
		}
	}
	function getWKT()
	{
		return ($this->wkt);
	}
	function getGML()
	{
		return ($this->toGML());
	}
	function getShapeArray()
	{
		return ($this->shapeArray);
	}
	function getGeomType()
	{
		return ($this->geomType[$count]);
	}
	function getNumOfShapes()
	{
		return sizeOf($this->getShapeArray());
	}
	function writeTag($type,$ns,$tag,$atts,$ind,$n)
	{
		$_str="";
		global $depth;
		if($ind!=False)
		{
			for($i=0;$i<$depth;$i++)
			{
				$_str=$_str."  ";
			}
		}
		if($ns!=null){
			$tag=$ns.":".$tag;
		}
		$_str.="<";
		if($type=="close"){
			$_str=$_str."/";
		}
		$_str=$_str.$tag;
		if(!empty($atts)){
			foreach ($atts as $key => $value) {
				$_str=$_str.' '.$key.'="'.$value.'"';
			}
		}
		if($type=="selfclose"){
			$_str=$_str."/";
		}
		$_str=$_str.">";
		if($n==True){
			$_str=$_str."\n";
		}
		return($_str);
	}
	/**
	* @return array
	* @param array $p
	* @param array $l1
	* @param array $l2
	* @desc Caculate the distance between a point and a line with two points and the point of perpendicular projection
	*/
	function distancePointToLine ($p,$l1,$l2)
	{
		$u=((($l2[0]-$l1[0])*($l1[1]-$p[1]))-(($l1[0]-$p[0])*($l2[1]-$l1[1])));
		$l=sqrt(pow(($l2[0]-$l1[0]),2)+pow(($l2[1]-$l1[1]),2));
		if ($l) $a=($u/$l);
		if ($a<0) $a=$a*-1;
		$diffX = $l1[0] - $l2[0];
		$diffY = $l1[1] - $l2[1];
		$l = sqrt(pow($diffX, 2) + pow($diffY, 2));
		if ($l) $r=(($p[0]-$l1[0])*($l2[0]-$l1[0])+($p[1]-$l1[1])*($l2[1]-$l1[1]))/pow($l,2);
		$newCoord[0]=$l1[0]+$r*($l2[0]-$l1[0]);
		$newCoord[1]=$l1[1]+$r*($l2[1]-$l1[1]);
		//Set the bounding box of line segment
		if ($l1[0]>=$l2[0])
		{
			$__maxX=$l1[0];
			$__minX=$l2[0];
		}
		else
		{
			$__maxX=$l2[0];
			$__minX=$l1[0];
		}
		if ($l1[1]>=$l2[1])
		{
			$__maxY=$l1[1];
			$__minY=$l2[1];
		}
		else
		{
			$__maxY=$l2[1];
			$__minY=$l1[1];
		}
		// If the point of perpendicular projection is outside bbox then set distance to FALSE
		if ($newCoord[0]>$__maxX || $newCoord[0]<$__minX || $newCoord[1]>$__maxY || $newCoord[1]<$__minY)
		{
			$a=FALSE;
			//echo "<script>alert('outside');</script>";
		}
		return (array($a,$newCoord));
	}
	function convertPoint($geom,$hasSrid=TRUE){
		global $depth;
		if(($hasSrid) && ($this->srid!=NULL)) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_str=$_str.$this->writeTag("open","gml","Point",$srid,True,True);
		$depth++;
		$_str=$_str.$this->writeTag("open","gml","coordinates",NULL,True,False);
		$_str=$_str.$this->convertCoordinatesToGML($geom);
		$_str=$_str.$this->writeTag("close","gml","coordinates",Null,False,True);
		$depth--;
		$_str=$_str.$this->writeTag("close","gml","Point",Null,True,True);
		return($_str);
	}
	function convertLineString($geom,$hasSrid=TRUE)
	{
		global $depth;
		if(($hasSrid) && ($this->srid!=NULL)) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_str.=$this->writeTag("open","gml","LineString",$srid,True,True);
		$depth++;
		$_str.=$this->writeTag("open","gml","coordinates",Null,True,False);
		$_str.=$this->convertCoordinatesToGML($geom);
		$_str.=$this->writeTag("close","gml","coordinates",Null,False,True);
		$depth--;
		$_str.=$this->writeTag("close","gml","LineString",Null,True,True);
		return($_str);
	}

	/**
	* @return unknown
	* @param unknown $rings
	* @param unknown $hasSrid
	* @desc Enter description here...
	*/
	function convertPolygon($rings,$hasSrid=TRUE)
	{
		global $depth;
		if(($hasSrid) && ($this->srid!=NULL)) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_str=$_str.$this->writeTag("open","gml","Polygon",$srid,True,True);
		$depth++;
		$pass=0;
		foreach ($rings as $ring) {
			if($pass==0){
				$boundTag="outer";
			}
			else{
				$boundTag="inner";
			}
			$_str=$_str.$this->writeTag("open","gml","".$boundTag."BoundaryIs",Null,True,True);
			$depth++;
			$_str=$_str.$this->writeTag("open","gml","LinearRing",Null,True,True);
			$depth++;
			$_str=$_str.$this->writeTag("open","gml","coordinates",Null,True,False);
			$_str=$_str.$this->convertCoordinatesToGML($ring);
			$_str=$_str.$this->writeTag("close","gml","coordinates",Null,False,True);
			$depth--;
			$_str=$_str.$this->writeTag("close","gml","LinearRing",Null,True,True);
			$depth--;
			$_str=$_str.$this->writeTag("close","gml","".$boundTag."BoundaryIs",Null,True,True);
			$pass++;
		}
		$depth--;
		$_str=$_str.$this->writeTag("close","gml","Polygon",Null,True,True);
		return($_str);
	}

	function convertCoordinatesToGML($_str)
	{
		$_str = str_replace(" ","&",$_str);
		$_str = str_replace(","," ",$_str);
		$_str = str_replace("&",",",$_str);
		$_str = str_replace("(","",$_str);
		$_str = str_replace(")","",$_str);
		return ($_str);
	}
}
class _point extends geometryfactory
{
	var $wkt;
	var $shapeArray;
	var $geomType;
	function _point($wkt,$srid)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->srid=$srid;
		$this->geomType[$count]='POINT';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);

	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{
		$__newWkt = $this->geomType[$count]."(".$this->shapeArray[0].")";
		$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		$_str="";
		$_str.=$this-> convertPoint($this->shapeArray[0]);
		return ($_str);
	}
}
class linestring extends geometryfactory
{
	/**
	* @var string
	*/
	var $wkt;
	/**
	* @var array
	*/
	var $shapeArray;
	var $geomType;
	function linestring($wkt,$srid)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->srid=$srid;
		$this->geomType[$count]='LINESTRING';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);

	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{
		$__newWkt = $this->geomType[$count]."(".$this->shapeArray[0].")";
		$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		$_str="";
		$_str.=$this-> convertLineString($this->shapeArray[0]);
		return ($_str);
	}
}
class polygon extends geometryfactory
{
	var $wkt;
	var $shapeArray;
	var $geomType;
	function polygon($wkt,$srid)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->srid=$srid;
		$this->geomType[$count]='POLYGON';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);

	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{$__newWkt = $this->geomType[$count]."(";
	for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
	{
		$__wktArray[$__i] = "(".$this->shapeArray[$__i].")";
	}
	$__newWkt = $__newWkt.implode(",", $__wktArray);
	$__newWkt = $__newWkt.")";
	$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		$_str="";
		$_str.=$this-> convertPolygon($this->shapeArray);
		return ($_str);
	}
}
class multipoint extends geometryfactory
{
	var $wkt;
	var $shapeArray;
	var $geomType;
	function multipoint($wkt,$srid)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->srid=$srid;
		$this->geomType[$count]='MULTIPOINT';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);

	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{
		$__newWkt = $this->geomType[$count]."(";
		for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
		{
			$__wktArray[$__i] = $this->shapeArray[$__i];
		}
		$__newWkt = $__newWkt.implode(",", $__wktArray);
		$__newWkt = $__newWkt.")";
		$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		if ($this->srid) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_str.=$this->writeTag("open","gml","MultiPoint",$srid,True,True);
		$depth++;
		for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
		{
			$_str.=$this->writeTag("open","gml","PointMember",Null,True,True);
			$depth++;
			$_str.=$this->convertPoint($this->shapeArray[$__i],FALSE);
			$depth--;
			$_str.=$this->writeTag("close","gml","PointMember",Null,True,True);
		}
		$depth--;
		$_str.=$this->writeTag("close","gml","MultiPoint",Null,True,True);
		return ($_str);
	}
}
class multilinestring extends geometryfactory
{
	var $wkt;
	var $shapeArray;
	var $geomType;
	function multilinestring($wkt)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->geomType[$count]='MULTILINESTRING';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);
	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{
		$__newWkt = $this->geomType[$count]."(";
		for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
		{
			$__wktArray[$__i] = "(".$this->shapeArray[$__i].")";
		}
		$__newWkt = $__newWkt.implode(",", $__wktArray);
		$__newWkt = $__newWkt.")";
		$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		if ($this->srid) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_str.=$this->writeTag("open","gml","MultiLineString",$srid,True,True);
		$depth++;
		for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
		{
			$_str.=$this->writeTag("open","gml","lineStringMember",Null,True,True);
			$depth++;
			$_str.=$this->convertLineString($this->shapeArray[$__i],FALSE);
			$depth--;
			$_str.=$this->writeTag("close","gml","lineStringMember",Null,True,True);
		}
		$depth--;
		$_str.=$this->writeTag("close","gml","MultiLineString",Null,True,True);
		return ($_str);
	}
}
class multipolygon extends geometryfactory
{
	var $wkt;
	var $shapeArray;
	var $geomType;
	var $isIsland;
	var $gml;
	function multipolygon($wkt,$srid)// constructor. wkt is set
	{
		$this->wkt=$wkt;
		$this->srid=$srid;
		$this->geomType[$count]='MULTIPOLYGON';
		$this->shapeArray=parent::deconstructionOfWKT($this->wkt);
	}
	function construction()// puts the deconstructed wkt together again and sets the wkt
	{
		$__newWkt = $this->geomType[$count]."(";
		for ($__i = 0; $__i < (sizeof($this->shapeArray)); $__i ++)
		{
			switch ($this->isIsland[$__i])//check if a shape is an island of another
			{
				case false:
				if ($this->isIsland[$__i+1]==true)// what is the next one?
				$__wktArray[$__i] = "((".$this->shapeArray[$__i].")";
				else
				$__wktArray[$__i] = "((".$this->shapeArray[$__i]."))";
				break;
				case true:
				if ($this->isIsland[$__i+1]==true)
				$__wktArray[$__i] = "(".$this->shapeArray[$__i].")";
				else
				$__wktArray[$__i] = "(".$this->shapeArray[$__i]."))";
				break;
			}
		}
		$__newWkt = $__newWkt.implode(",", $__wktArray);
		$__newWkt = $__newWkt.")";
		$this->wkt=$__newWkt;
	}
	function toGML()
	{
		global $depth;
		if ($this->srid) $srid=array("srsName"=>$this->srid);
		else $srid=NULL;
		$_str="";
		$_polys=array();
		$__i=0;
		while($this->shapeArray[$__i])
		{
			if ($this->isIsland[$__i+1])
			{
				$_rings=array($this->shapeArray[$__i]);
				while ($this->isIsland[$__i+1])
				{
					array_push($_rings,$this->shapeArray[$__i+1]);
					$__i++;
				}
				array_push($_polys,$_rings);
				$__i++;
			}
			else
			{
				array_push($_polys,array($this->shapeArray[$__i]));
				$__i++;
			}
		}
		$_str=$_str.$this->writeTag("open","gml","MultiPolygon",$srid,True,True);
		$depth++;
		foreach ($_polys as $__array)
		{
			$_str=$_str.$this->writeTag("open","gml","polygonMember",Null,True,True);
			$depth++;
			$_str=$_str.$this->convertPolygon($__array,FALSE);
			$depth--;
			$_str=$_str.$this->writeTag("close","gml","polygonMember",Null,True,True);
		}
		$depth--;
		$_str=$_str.$this->writeTag("close","gml","MultiPolygon",Null,True,True);
		return ($_str);
	}
}
class geometryCollection extends geometryfactory
{
	var $geometryArray;
	function geometryCollection($wktArray)
	{
		foreach($wktArray as $__key => $__value)
		{
			$this->geometryArray[$__key]=parent::createGeometry($__value);
		}
	}
	function getVertices()
	{
		foreach($this->geometryArray as $__geometry)
		{
			$__verticeStr="";

			foreach($__geometry->getShapeArray() as $__value)
			{
				$__verticeStr=$__verticeStr.$__value.",";
			}
			$verticeStr=$verticeStr.$__verticeStr;
		}
		// remove the last comma
		$verticeStr=substr($verticeStr, 0, strlen($verticeStr) - 1);
		return($verticeStr);
	}
	function getShapes()
	{
		$__shapeArray=array();
		foreach($this->geometryArray as $__geometry)
		{


			foreach($__geometry->getShapeArray() as $__value)
			{
				array_push($__shapeArray,$__value);
			}

		}
		$shapeArray=$__shapeArray;
		return($shapeArray);
	}
	function getGeometryArray()
	{
		return($this->geometryArray);
	}
}
class gmlConverter
{
	var $parser;
	var $geomType;
	var $wkt;
	var $isIsland;
	var $wktCoords;
	var $isPreviousIsland;
	var $splitTag;
	var $srid;

	function gmlConverter()
	{
		$this->xml();
	}
	function xml()
	{
		$this -> parser = xml_parser_create();
		xml_set_object($this -> parser, & $this);
		xml_set_element_handler($this -> parser, "startElement", "endElement");
		xml_set_character_data_handler($this -> parser, "characterData");
	}
	/**
	* @return array
	* @param string $gml
	* @param string $splitTag
	* @desc Enter description here...
	*/
	function gmlToWKT($gml,$splitTag="GML:FEATUREMEMBER")
	{
		global $count;
		// Clen up messy gml. Remove spaces and tabs.
		$gml=ereg_replace("\t", "",$gml);
		$gml=ereg_replace("\r", "",$gml);
		$gml=ereg_replace("\n", "",$gml);
		$gml=ereg_replace(">[[:space:]]+",">",$gml);
		$gml=ereg_replace("[[:space:]]+<", "<",$gml);
//		echo "<!-- gml /".$gml."-->";
		$this->splitTag=strtoupper($splitTag);
		$count=0;
		$currentTag = "";
		xml_parse($this -> parser, $gml);
		// clean up
		xml_parser_free($this -> parser);
		for ($__i = 0; $__i < sizeof($this->wktCoords); $__i ++)
		{
			if ($this->geomType[$__i]=="MULTIPOINT" || $this->geomType[$__i]=="MULTIPOLYGON" || $this->geomType[$__i]=="MULTILINESTRING") $this->wktCoords[$__i]=substr($this->wktCoords[$__i], 0, strlen($this->wktCoords[$__i]) - 1);
			$this->wktCoords[$__i]=$this->geomType[$__i]."(".$this->wktCoords[$__i].")";
		}
		return(array($this->wktCoords,$this->srid));
	}
	function startElement($parser, $name, $attrs)
	{
		global $currentTag;	//used by function characterData when parsing xml data
		global $count;
		$currentTag = $name;
		//echo $count;
		if ($attrs['SRSNAME']!="") $this->srid[$count]=$this->parseEpsgCode($attrs['SRSNAME']);
		switch ($currentTag)
		{

			case "GML:POINT" :
			$this->geomType[$count]="POINT";

			break;
			case "GML:LINESTRING" :
			$this->geomType[$count]="LINESTRING";
			break;
			case "GML:POLYGON" :
			$this->geomType[$count]="POLYGON";
			break;
			case "GML:MULTIPOINT" :
			$this->geomType[$count]="MULTIPOINT";
			break;
			case "GML:MULTILINESTRING" :
			$this->geomType[$count]="MULTILINESTRING";
			break;
			case "GML:MULTIPOLYGON" :
			$this->geomType[$count]="MULTIPOLYGON";
			break;
			case "GML:MULTIGEOMETRY" :
			$this->geomType[$count]="MULTIGEOMETRY";
			break;
			case "GML:POLYGONMEMBER":
			$this->wktCoords[$count].="(";
			break;
			case "GML:LINESTRINGMEMBER":
			$this->wktCoords[$count].="(";
			break;
			case "GML:INNERBOUNDARYIS";
			$this->isIsland=true;
			break;
			case "GML:OUTERBOUNDARYIS";
			$this->isIsland=false;
			break;

		}
	}
	function endElement($parser, $name)
	{
		global $currentTag;
		global $count;
		$currentTag=$name;
		//echo $currentTag;
		switch ($currentTag)
		{

			case "GML:POLYGONMEMBER":
			$this->wktCoords[$count].="),";
			break;
			case "GML:LINESTRINGMEMBER":
			$this->wktCoords[$count].="),";
			break;
			case "GML:POINTMEMBER":
			$this->wktCoords[$count].=",";
			break;
			//Read the last tag and set the main feature geometry type.
			case "GML:POINT" :
			$this->geomType[$count]="POINT";
			break;
			case "GML:LINESTRING" :
			$this->geomType[$count]="LINESTRING";
			break;
			case "GML:POLYGON" :
			$this->geomType[$count]="POLYGON";
			break;
			case "GML:MULTIPOINT" :
			$this->geomType[$count]="MULTIPOINT";
			break;
			case "GML:MULTILINESTRING" :
			$this->geomType[$count]="MULTILINESTRING";
			break;
			case "GML:MULTIPOLYGON" :
			$this->geomType[$count]="MULTIPOLYGON";
			break;
			case "GML:MULTIGEOMETRY" :
			$this->geomType[$count]="MULTIGEOMETRY";
			break;
			case $this->splitTag :
			$count++;
			break;


		}
		$currentTag = null;
	}
	function characterData($parser, $data)
	{
		global $concatCoords;
		global $currentTag;
		global $count;
		// echo $this->geomType[$count];
		//echo $currentTag;

		switch ($currentTag)
		{
			case "GML:COORDINATES" :
			$concatCoords.=$data; // concat the data in case of the 1024 char limit is exceeded
			if (strlen($data)<1024)// To defeat the 1024 char limit on the sax parser
			{
				if ($this->geomType[$count]=="POINT")
				{
					$this->wktCoords[$count].=$this->convertCoordinatesToWKT($concatCoords);
				}
				else if ($this->geomType[$count]=="LINESTRING")
				{
					$this->wktCoords[$count].=$this->convertCoordinatesToWKT($concatCoords);
				}
				else if ($this->geomType[$count]=="POLYGON")
				{
					if ($this->isIsland==true) $this->wktCoords[$count].=",";
					$this->wktCoords[$count].="(".$this->convertCoordinatesToWKT($concatCoords).")";
				}
			$concatCoords="";
			}
			break;
			case "PROPERTYNAME";
			$this->filterPropertyName[$data]=$count;
			break;
		}
	}
	function convertCoordinatesToWKT($_str)
	{
		$_str = str_replace(" ","&",$_str);
		$_str = str_replace(","," ",$_str);
		$_str = str_replace("&",",",$_str);
		return ($_str);
	}
	function parseEpsgCode($epsg)
	{
		if (strtoupper(substr($epsg, 0, 5)=="EPSG:")) $epsg=substr($epsg, 5,strlen($epsg));
		return $epsg;
	}
}
?>
Return current item: AppForMap