batch/framework/map/ShapeFile.inc.php
2012-10-16 08:08:03 +00:00

960 lines
30 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* This class is under GPL Licencense Agreement
* @author Juan Carlos Gonzalez Ulloa <jgonzalez@innox.com.mx>
* Innovacion Inteligente S de RL de CV (Innox)
* Av. Abraham Lincoln 28 B
* Col. Vallarta Norte
* Guadalajara, Jalisco. México.
*
* Class to read SHP files and modify the DBF related information
* Just create the object and all the records will be saved in $shp->records
* Each record has the "shp_data" and "dbf_data" arrays with the record information
* You can modify the DBF information using the $shp_record->setDBFInformation($data)
* The $data must be an array with the DBF's row data.
*
* Performance issues:
* Because the class opens and fetches all the information (records/dbf info)
* from the file, the loading time and memory amount neede may be way to much.
* Example:
* 15 seconds loading a 210907 points shape file
* 60Mb memory limit needed
* Athlon XP 2200+
* Mandrake 10 OS
*
* EXAMPLE
$shp = new ShapeFile("file.shp"); // along this file the class will use file.shx and file.dbf
// Let's see all the records:
foreach($shp->records as $record){
echo "<pre>"; // just to format
print_r($record->shp_data); // All the data related to the poligon
print_r($record->dbf_data); // The alphanumeric information related to the figure
echo $shp->getRecordClass()."\n"; // The poligon type
echo "</pre>";
}
Here you have all the information contained within a shape file.
----------------------------------------------------------------------
MODIFIED 15-MARCH-2006 by Marcel Mateescu <marcelmateescu@sourceforge.net>
to run without the DBASE extensiopn of PHP using dbf_class.php
*/
include("dbf_class.php");
// Configuration
define("SHOW_ERRORS", true);
define("DEBUG", false);
// Constants
define("XY_POINT_RECORD_LENGTH", 16);
// Strings
define("ERROR_FILE_NOT_FOUND", "SHP File not found [%s]");
define("INEXISTENT_RECORD_CLASS", "Unable to determine shape record type [%i]");
define("INEXISTENT_FUNCTION", "Unable to find reading function [%s]");
define("INEXISTENT_DBF_FILE", "Unable to open (read/write) SHP's DBF file [%s]");
define("INCORRECT_DBF_FILE", "Unable to read SHP's DBF file [%s]");
define("UNABLE_TO_WRITE_DBF_FILE", "Unable to write DBF file [%s]");
class ShapeFile{
var $file_name;
var $fp;
var $error_message = "";
var $show_errors = SHOW_ERRORS;
var $shp_bounding_box = array();
var $shp_type = 0;
var $records;
var $dbf;
function ShapeFile($file_name){
$this->file_name = $file_name;
_d("Opening [$file_name]");
if(!is_readable($file_name)){
return $this->setError( sprintf(ERROR_FILE_NOT_FOUND, $file_name) );
}
$this->fp = fopen($this->file_name, "rb");
$this->_fetchShpBasicConfiguration();
$this->getDBFHeader();
$this->_fetchRecords();
}
// Data fetchers
function _fetchShpBasicConfiguration(){
_d("Reading basic information");
fseek($this->fp, 32, SEEK_SET);
$this->shp_type = readAndUnpack("i", fread($this->fp, 4));
_d("SHP type detected: ".$this->shp_type);
$this->shp_bounding_box = readBoundingBox($this->fp);
//_d("SHP bounding box detected: miX=".$this->shp_bounding_box["xmin"]." miY=".$this->shp_bounding_box["ymin"]." maX=".$this->shp_bounding_box["xmax"]." maY=".$this->shp_bounding_box["ymax"]);
}
function _fetchRecords(){
fseek($this->fp, 100);
$recid=0;
while(!feof($this->fp)){
$shp_record = new ShapeRecord($this->fp, $this->file_name);
if($shp_record->error_message != ""){
return false;
}
$this->records[] = $shp_record;
break;
}
}
function fetchNextRecord(){
while(!feof($this->fp)){
$shp_record = new ShapeRecord($this->fp, $this->file_name);
if($shp_record->error_message != ""){
return false;
}
$this->records[] = $shp_record;
break;
}
}
function getDBFHeader(){
$dbf_filename = processDBFFileName($this->file_name);
$dbf_data = array();
// if(is_readable($dbf_data)){
//mod mm $dbf = dbase_open($dbf_filename, 1);
$this->dbf = new dbf_class($dbf_filename);
// solo en PHP5 $dbf_data = dbase_get_header_info($dbf);
// }
}
// General functions
function setError($error){
$this->error_message = $error;
if($this->show_errors){
echo $error."\n";
}
return false;
}
function closeFile(){
if($this->fp){
fclose($this->fp);
}
}
}
/**
* ShapeRecord
*
*/
class ShapeRecord{
var $fp;
var $dbf = null;
var $record_number = null;
var $content_length = null;
var $record_shape_type = null;
var $error_message = "";
var $shp_data = array();
var $dbf_data = array();
var $file_name = "";
var $record_class = array( 0 => "RecordNull",
1 => "RecordPoint",
8 => "RecordMultiPoint",
3 => "RecordPolyLine",
5 => "RecordPolygon");
function ShapeRecord(&$fp, $file_name){
$this->fp = $fp;
_d("Shape record created at byte ".ftell($fp));
$this->_readHeader();
$function_name = "read".$this->getRecordClass();
_d("Calling reading function [$function_name] starting at byte ".ftell($fp));
if(function_exists($function_name)){
$this->shp_data = $function_name($this->fp);
} else {
$this->setError( sprintf(INEXISTENT_FUNCTION, $function_name) );
}
$this->file_name = processDBFFileName($file_name);
$this->_fetchDBFInformation();
}
function _readHeader(){
$this->record_number = readAndUnpack("N", fread($this->fp, 4));
$this->content_length = readAndUnpack("N", fread($this->fp, 4));
$this->record_shape_type = readAndUnpack("i", fread($this->fp, 4));
_d("Shape Record ID=".$this->record_number." ContentLength=".$this->content_length." RecordShapeType=".$this->record_shape_type."\nEnding byte ".ftell($this->fp)."\n");
}
function getRecordClass(){
if(!isset($this->record_class[$this->record_shape_type])){
_d("Unable to find record class ($this->record_shape_type) [".getArray($this->record_class)."]");
return $this->setError( sprintf(INEXISTENT_RECORD_CLASS, $this->record_shape_type) );
}
_d("Returning record class ($this->record_shape_type) ".$this->record_class[$this->record_shape_type]);
return $this->record_class[$this->record_shape_type];
}
function setError($error){
$this->error_message = $error;
return false;
}
function getShpData(){
return $this->shp_data;
}
function _openDBFFile($check_writeable = false){
$dbffilename =$this->file_name;
if(1==1){
//mm $this->dbf = dbase_open($this->file_name, ($check_writeable ? 2 : 0));
$this->dbf = new dbf_class($dbffilename);
if(!$this->dbf){
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
} else {
$this->setError( sprintf(INEXISTENT_DBF_FILE, $this->file_name) );
}
}
function _closeDBFFile(){
if($this->dbf){
// dbase_close($this->dbf);
$this->dbf = null;
}
}
function _fetchDBFInformation(){
// print_r(stream_context_get_options($this->fp));
$this->_openDBFFile();
if($this->dbf) {
//°° $this->dbf_data = dbase_get_record_with_names($this->dbf, $this->record_number);
$this->dbf_data = $this->dbf->getRow($this->record_number);
} else {
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
$this->_closeDBFFile();
}
function setDBFInformation($row_array){
$this->_openDBFFile(true);
if($this->dbf) {
unset($row_array["deleted"]);
if(!dbase_replace_record($this->dbf, array_values($row_array), $this->record_number)){
$this->setError( sprintf(UNABLE_TO_WRITE_DBF_FILE, $this->file_name) );
} else {
$this->dbf_data = $row_array;
}
} else {
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
$this->_closeDBFFile();
}
}
/**
* Reading functions
*/
function readRecordNull(&$fp, $read_shape_type = false){
$data = array();
if($read_shape_type) $data += readShapeType($fp);
_d("Returning Null shp_data array = ".getArray($data));
return $data;
}
$point_count = 0;
function readRecordPoint(&$fp, $create_object = false){
global $point_count;
$data = array();
$data["x"] = readAndUnpack("d", fread($fp, 8));
$data["y"] = readAndUnpack("d", fread($fp, 8));
//_d("Returning Point shp_data array = ".getArray($data));
$point_count++;
return $data;
}
function readRecordMultiPoint(&$fp){
$data = readBoundingBox($fp);
$data["numpoints"] = readAndUnpack("i", fread($fp, 4));
_d("MultiPoint numpoints = ".$data["numpoints"]);
for($i = 0; $i <= $data["numpoints"]; $i++){
$data["points"][] = readRecordPoint($fp);
}
_d("Returning MultiPoint shp_data array = ".getArray($data));
return $data;
}
function readRecordPolyLine(&$fp){
$data = readBoundingBox($fp);
$data["numparts"] = readAndUnpack("i", fread($fp, 4));
$data["numpoints"] = readAndUnpack("i", fread($fp, 4));
_d("PolyLine numparts = ".$data["numparts"]." numpoints = ".$data["numpoints"]);
for($i=0; $i<$data["numparts"]; $i++){
$data["parts"][$i] = readAndUnpack("i", fread($fp, 4));
_d("PolyLine adding point index= ".$data["parts"][$i]);
}
$points_initial_index = ftell($fp);
_d("Reading points; initial index = $points_initial_index");
$points_read = 0;
foreach($data["parts"] as $part_index => $point_index){
//fseek($fp, $points_initial_index + $point_index);
_d("Seeking initial index point [".($points_initial_index + $point_index)."]");
if(!isset($data["parts"][$part_index]["points"]) || !is_array($data["parts"][$part_index]["points"])){
$data["parts"][$part_index] = array();
$data["parts"][$part_index]["points"] = array();
}
while( ! in_array( $points_read, $data["parts"]) && $points_read < $data["numpoints"] && !feof($fp)){
set_time_limit(160);
$data["parts"][$part_index]["points"][] = readRecordPoint($fp, true);
$points_read++;
}
}
fseek($fp, $points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH));
_d("Seeking end of points section [".($points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH))."]");
return $data;
}
function readRecordPolygon(&$fp){
_d("Polygon reading; applying readRecordPolyLine function");
return readRecordPolyLine($fp);
}
/**
* General functions
*/
function processDBFFileName($dbf_filename){
_d("Received filename [$dbf_filename]");
if(!strstr($dbf_filename, ".")){
$dbf_filename .= ".dbf";
}
if(substr($dbf_filename, strlen($dbf_filename)-3, 3) != "dbf"){
$dbf_filename = substr($dbf_filename, 0, strlen($dbf_filename)-3)."dbf";
}
_d("Ended up like [$dbf_filename]");
return $dbf_filename;
}
function readBoundingBox(&$fp){
$data = array();
$data["xmin"] = readAndUnpack("d",fread($fp, 8));
$data["ymin"] = readAndUnpack("d",fread($fp, 8));
$data["xmax"] = readAndUnpack("d",fread($fp, 8));
$data["ymax"] = readAndUnpack("d",fread($fp, 8));
_d("Bounding box read: miX=".$data["xmin"]." miY=".$data["ymin"]." maX=".$data["xmax"]." maY=".$data["ymax"]);
return $data;
}
function readAndUnpack($type, $data){
if(!$data) return $data;
return current(unpack($type, $data));
}
function _d($debug_text){
if(DEBUG){
echo $debug_text."\n";
}
}
function getArray($array){
ob_start();
print_r($array);
$contents = ob_get_contents();
ob_get_clean();
return $contents;
}
/**
* This class is under GPL Licencense Agreement
* @author Juan Carlos Gonzalez Ulloa <jgonzalez@innox.com.mx>
* Innovacion Inteligente S de RL de CV (Innox)
* Lopez Mateos Sur 2077 - Z16
* Col. Jardines de Plaza del Sol
* Guadalajara, Jalisco
* CP 44510
* Mexico
*
* Class to read SHP files and modify the DBF related information
* Just create the object and all the records will be saved in $shp->records
* Each record has the "shp_data" and "dbf_data" arrays with the record information
* You can modify the DBF information using the $shp_record->setDBFInformation($data)
* The $data must be an array with the DBF's row data.
*
* Performance issues:
* Because the class opens and fetches all the information (records/dbf info)
* from the file, the loading time and memory amount neede may be way to much.
* Example:
* 15 seconds loading a 210907 points shape file
* 60Mb memory limit needed
* Athlon XP 2200+
* Mandrake 10 OS
*
*
*
* Edited by David Granqvist March 2008 for better performance on large files
* This version only get the information it really needs
* Get one record at a time to save memory, means that you can work with very large files.
* Does not load the information until you tell it too (saves time)
* Added an option to not read the polygon points can be handy sometimes, and saves time :-)
*
* Example:
//sets the options to show the polygon points, 'noparts' => true would skip that and save time
$options = array('noparts' => false);
$shp = new ShapeFile("../../php/shapefile/file.shp",$options);
//Dump the ten first records
$i = 0;
while ($record = $shp->getNext() and $i<10) {
$dbf_data = $record->getDbfData();
$shp_data = $record->getShpData();
//Dump the information
var_dump($dbf_data);
var_dump($shp_data);
$i++;
}
*
*
// Configuration
define("SHOW_ERRORS", true);
define("DEBUG", false);
// Constants
define("XY_POINT_RECORD_LENGTH", 16);
// Strings
define("ERROR_FILE_NOT_FOUND", "SHP File not found [%s]");
define("INEXISTENT_RECORD_CLASS", "Unable to determine shape record type [%i]");
define("INEXISTENT_FUNCTION", "Unable to find reading function [%s]");
define("INEXISTENT_DBF_FILE", "Unable to open (read/write) SHP's DBF file [%s]");
define("INCORRECT_DBF_FILE", "Unable to read SHP's DBF file [%s]");
define("UNABLE_TO_WRITE_DBF_FILE", "Unable to write DBF file [%s]");
class ShapeFile{
private $file_name;
private $fp;
//Used to fasten up the search between records;
private $dbf_filename = null;
//Starting position is 100 for the records
private $fpos = 100;
private $error_message = "";
private $show_errors = SHOW_ERRORS;
private $shp_bounding_box = array();
private $shp_type = 0;
public $records;
function ShapeFile($file_name,$options=array()){
$this->options = $options;
$this->file_name = $file_name;
//_d("Opening [$file_name]");
if(!is_readable($file_name)){
return $this->setError( sprintf(ERROR_FILE_NOT_FOUND, $file_name) );
}
$this->fp = fopen($this->file_name, "rb");
$this->_fetchShpBasicConfiguration();
//Set the dbf filename
$this->dbf_filename = processDBFFileName($this->file_name);
}
public function getError(){
return $this->error_message;
}
function __destruct()
{
$this->closeFile();
}
// Data fetchers
private function _fetchShpBasicConfiguration(){
//_d("Reading basic information");
fseek($this->fp, 32, SEEK_SET);
$this->shp_type = readAndUnpack("i", fread($this->fp, 4));
//_d("SHP type detected: ".$this->shp_type);
$this->shp_bounding_box = readBoundingBox($this->fp);
////_d("SHP bounding box detected: miX=".$this->shp_bounding_box["xmin"]." miY=".$this->shp_bounding_box["ymin"]." maX=".$this->shp_bounding_box["xmax"]." maY=".$this->shp_bounding_box["ymax"]);
}
public function getNext(){
if (!feof($this->fp)) {
fseek($this->fp, $this->fpos);
$shp_record = new ShapeRecord($this->fp, $this->dbf_filename,$this->options);
if($shp_record->getError() != ""){
return false;
}
$this->fpos = $shp_record->getNextRecordPosition();
return $shp_record;
}
return false;
}
/*Alpha, not working
public function _resetFileReading(){
rewind($this->fp);
$this->fpos = 0;
$this->_fetchShpBasicConfiguration();
}*/
/* Takes too much memory
function _fetchRecords(){
fseek($this->fp, 100);
while(!feof($this->fp)){
$shp_record = new ShapeRecord($this->fp, $this->file_name);
if($shp_record->error_message != ""){
return false;
}
$this->records[] = $shp_record;
}
}
*
//Not Used
/* private function getDBFHeader(){
$dbf_data = array();
if(is_readable($dbf_data)){
$dbf = dbase_open($this->dbf_filename , 1);
// solo en PHP5 $dbf_data = dbase_get_header_info($dbf);
echo dbase_get_header_info($dbf);
}
}
*
// General functions
private function setError($error){
$this->error_message = $error;
if($this->show_errors){
echo $error."\n";
}
return false;
}
private function closeFile(){
if($this->fp){
fclose($this->fp);
}
}
}
//
// ShapeRecord
//
class ShapeRecord{
private $fp;
private $fpos = null;
private $dbf = null;
private $record_number = null;
private $content_length = null;
private $record_shape_type = null;
private $error_message = "";
private $shp_data = array();
private $dbf_data = array();
private $file_name = "";
private $record_class = array( 0 => "RecordNull",
1 => "RecordPoint",
8 => "RecordMultiPoint",
3 => "RecordPolyLine",
5 => "RecordPolygon",
13 => "RecordMultiPointZ",
11 => "RecordPointZ");
function ShapeRecord(&$fp, $file_name,$options){
$this->fp = $fp;
$this->fpos = ftell($fp);
$this->options = $options;
//_d("Shape record created at byte ".ftell($fp));
if (feof($fp)) {
echo "end ";
exit;
}
$this->_readHeader();
$this->file_name = $file_name;
}
public function getNextRecordPosition(){
$nextRecordPosition = $this->fpos + ((4 + $this->content_length )* 2);
return $nextRecordPosition;
}
private function _readHeader(){
$this->record_number = readAndUnpack("N", fread($this->fp, 4));
$this->content_length = readAndUnpack("N", fread($this->fp, 4));
$this->record_shape_type = readAndUnpack("i", fread($this->fp, 4));
//_d("Shape Record ID=".$this->record_number." ContentLength=".$this->content_length." RecordShapeType=".$this->record_shape_type."\nEnding byte ".ftell($this->fp)."\n");
}
private function getRecordClass(){
if(!isset($this->record_class[$this->record_shape_type])){
//_d("Unable to find record class ($this->record_shape_type) [".getArray($this->record_class)."]");
return $this->setError( sprintf(INEXISTENT_RECORD_CLASS, $this->record_shape_type) );
}
//_d("Returning record class ($this->record_shape_type) ".$this->record_class[$this->record_shape_type]);
return $this->record_class[$this->record_shape_type];
}
private function setError($error){
$this->error_message = $error;
return false;
}
public function getError(){
return $this->error_message;
}
public function getShpData(){
$function_name = "read".$this->getRecordClass();
//_d("Calling reading function [$function_name] starting at byte ".ftell($fp));
if(function_exists($function_name)){
$this->shp_data = $function_name($this->fp,$this->options);
} else {
$this->setError( sprintf(INEXISTENT_FUNCTION, $function_name) );
}
return $this->shp_data;
}
public function getDbfData(){
$this->_fetchDBFInformation();
return $this->dbf_data;
}
private function _openDBFFile($check_writeable = false){
$check_function = $check_writeable ? "is_writable" : "is_readable";
if($check_function($this->file_name)){
$this->dbf = dbase_open($this->file_name, ($check_writeable ? 2 : 0));
if(!$this->dbf){
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
} else {
$this->setError( sprintf(INEXISTENT_DBF_FILE, $this->file_name) );
}
}
private function _closeDBFFile(){
if($this->dbf){
dbase_close($this->dbf);
$this->dbf = null;
}
}
private function _fetchDBFInformation(){
$this->_openDBFFile();
if($this->dbf) {
//En este punto salta un error si el registro 0 está vacio.
//Ignoramos los errores, ja que aún así todo funciona perfecto.
$this->dbf_data = @dbase_get_record_with_names($this->dbf, $this->record_number);
} else {
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
$this->_closeDBFFile();
}
public function setDBFInformation($row_array){
$this->_openDBFFile(true);
if($this->dbf) {
unset($row_array["deleted"]);
if(!dbase_replace_record($this->dbf, array_values($row_array), $this->record_number)){
$this->setError( sprintf(UNABLE_TO_WRITE_DBF_FILE, $this->file_name) );
} else {
$this->dbf_data = $row_array;
}
} else {
$this->setError( sprintf(INCORRECT_DBF_FILE, $this->file_name) );
}
$this->_closeDBFFile();
}
}
//
// Reading functions
//
function readRecordNull(&$fp, $read_shape_type = false,$options = null){
$data = array();
if($read_shape_type) $data += readShapeType($fp);
//_d("Returning Null shp_data array = ".getArray($data));
return $data;
}
$point_count = 0;
function readRecordPoint(&$fp, $create_object = false,$options = null){
global $point_count;
$data = array();
$data["x"] = readAndUnpack("d", fread($fp, 8));
$data["y"] = readAndUnpack("d", fread($fp, 8));
////_d("Returning Point shp_data array = ".getArray($data));
$point_count++;
return $data;
}
function readRecordPointZ(&$fp, $create_object = false,$options = null){
global $point_count;
$data = array();
$data["x"] = readAndUnpack("d", fread($fp, 8));
$data["y"] = readAndUnpack("d", fread($fp, 8));
// $data["z"] = readAndUnpack("d", fread($fp, 8));
// $data["m"] = readAndUnpack("d", fread($fp, 8));
////_d("Returning Point shp_data array = ".getArray($data));
$point_count++;
return $data;
}
function readRecordPointZSP($data, &$fp){
$data["z"] = readAndUnpack("d", fread($fp, 8));
return $data;
}
function readRecordPointMSP($data, &$fp){
$data["m"] = readAndUnpack("d", fread($fp, 8));
return $data;
}
function readRecordMultiPoint(&$fp,$options = null){
$data = readBoundingBox($fp);
$data["numpoints"] = readAndUnpack("i", fread($fp, 4));
//_d("MultiPoint numpoints = ".$data["numpoints"]);
for($i = 0; $i <= $data["numpoints"]; $i++){
$data["points"][] = readRecordPoint($fp);
}
//_d("Returning MultiPoint shp_data array = ".getArray($data));
return $data;
}
function readRecordPolyLine(&$fp,$options = null){
$data = readBoundingBox($fp);
$data["numparts"] = readAndUnpack("i", fread($fp, 4));
$data["numpoints"] = readAndUnpack("i", fread($fp, 4));
//_d("PolyLine numparts = ".$data["numparts"]." numpoints = ".$data["numpoints"]);
if (isset($options['noparts']) && $options['noparts']==true) {
//Skip the parts
$points_initial_index = ftell($fp)+4*$data["numparts"];
$points_read = $data["numpoints"];
}
else{
for($i=0; $i<$data["numparts"]; $i++){
$data["parts"][$i] = readAndUnpack("i", fread($fp, 4));
//_d("PolyLine adding point index= ".$data["parts"][$i]);
}
$points_initial_index = ftell($fp);
//_d("Reading points; initial index = $points_initial_index");
$points_read = 0;
foreach($data["parts"] as $part_index => $point_index){
//fseek($fp, $points_initial_index + $point_index);
//_d("Seeking initial index point [".($points_initial_index + $point_index)."]");
if(!isset($data["parts"][$part_index]["points"]) || !is_array($data["parts"][$part_index]["points"])){
$data["parts"][$part_index] = array();
$data["parts"][$part_index]["points"] = array();
}
while( ! in_array( $points_read, $data["parts"]) && $points_read < $data["numpoints"] && !feof($fp)){
$data["parts"][$part_index]["points"][] = readRecordPoint($fp, true);
$points_read++;
}
}
}
fseek($fp, $points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH));
//_d("Seeking end of points section [".($points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH))."]");
return $data;
}
function readRecordMultiPointZ(&$fp,$options = null){
$data = readBoundingBox($fp);
$data["numparts"] = readAndUnpack("i", fread($fp, 4));
$data["numpoints"] = readAndUnpack("i", fread($fp, 4));
// $fileX = 40 + (16*$data["numpoints"]);
// $fileY = $fileX + 16 + (8*$data["numpoints"]);
$fileX = 44 + (4*$data["numparts"]);
$fileY = $fileX + (16*$data["numpoints"]);
$fileZ = $fileY + 16 + (8*$data["numpoints"]);
/*
Note: X = 44 + (4 * NumParts), Y = X + (16 * NumPoints), Z = Y + 16 + (8 * NumPoints)
*
//_d("PolyLine numparts = ".$data["numparts"]." numpoints = ".$data["numpoints"]);
if (isset($options['noparts']) && $options['noparts']==true) {
//Skip the parts
$points_initial_index = ftell($fp)+4*$data["numparts"];
$points_read = $data["numpoints"];
}
else{
for($i=0; $i<$data["numparts"]; $i++){
$data["parts"][$i] = readAndUnpack("i", fread($fp, 4));
//_d("PolyLine adding point index= ".$data["parts"][$i]);
}
$points_initial_index = ftell($fp);
//_d("Reading points; initial index = $points_initial_index");
$points_read = 0;
foreach($data["parts"] as $part_index => $point_index){
//fseek($fp, $points_initial_index + $point_index);
//_d("Seeking initial index point [".($points_initial_index + $point_index)."]");
if(!isset($data["parts"][$part_index]["points"]) || !is_array($data["parts"][$part_index]["points"])){
$data["parts"][$part_index] = array();
$data["parts"][$part_index]["points"] = array();
}
while( ! in_array( $points_read, $data["parts"]) && $points_read < $data["numpoints"]/* && !feof($fp)*
){
$data["parts"][$part_index]["points"][] = readRecordPoint($fp, true);
$points_read++;
}
}
$data['Zmin'] = readAndUnpack("d", fread($fp, 8));
$data['Zmax'] = readAndUnpack("d", fread($fp, 8));
foreach($data["parts"] as $part_index => $point_index){
foreach($point_index["points"] as $n => $p){
$data["parts"][$part_index]['points'][$n] = readRecordPointZSP($p, $fp, true);
}
}
$data['Mmin'] = readAndUnpack("d", fread($fp, 8));
$data['Mmax'] = readAndUnpack("d", fread($fp, 8));
foreach($data["parts"] as $part_index => $point_index){
foreach($point_index["points"] as $n => $p){
$data["parts"][$part_index]['points'][$n] = readRecordPointMSP($p, $fp, true);
}
}
}
fseek($fp, $points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH));
//_d("Seeking end of points section [".($points_initial_index + ($points_read * XY_POINT_RECORD_LENGTH))."]");
return $data;
}
function readRecordPolygon(&$fp,$options = null){
//_d("Polygon reading; applying readRecordPolyLine function");
return readRecordPolyLine($fp,$options);
}
/**
* General functions
*
function processDBFFileName($dbf_filename){
//_d("Received filename [$dbf_filename]");
if(!strstr($dbf_filename, ".")){
$dbf_filename .= ".dbf";
}
if(substr($dbf_filename, strlen($dbf_filename)-3, 3) != "dbf"){
$dbf_filename = substr($dbf_filename, 0, strlen($dbf_filename)-3)."dbf";
}
//_d("Ended up like [$dbf_filename]");
return $dbf_filename;
}
function readBoundingBox(&$fp){
$data = array();
$data["xmin"] = readAndUnpack("d",fread($fp, 8));
$data["ymin"] = readAndUnpack("d",fread($fp, 8));
$data["xmax"] = readAndUnpack("d",fread($fp, 8));
$data["ymax"] = readAndUnpack("d",fread($fp, 8));
//_d("Bounding box read: miX=".$data["xmin"]." miY=".$data["ymin"]." maX=".$data["xmax"]." maY=".$data["ymax"]);
return $data;
}
function readAndUnpack($type, $data){
if(!$data) return $data;
return current(unpack($type, $data));
}
function _d($debug_text){
if(DEBUG){
echo $debug_text."\n";
}
}
function getArray($array){
ob_start();
print_r($array);
$contents = ob_get_contents();
ob_get_clean();
return $contents;
}*/
?>