1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* phpMyAdmin ShapeFile library |
4
|
|
|
* <https://github.com/phpmyadmin/shapefile/> |
5
|
|
|
* |
6
|
|
|
* Copyright 2006-2007 Ovidio <ovidio AT users.sourceforge.net> |
7
|
|
|
* Copyright 2016 Michal Čihař <[email protected]> |
8
|
|
|
* |
9
|
|
|
* This program is free software; you can redistribute it and/or |
10
|
|
|
* modify it under the terms of the GNU General Public License |
11
|
|
|
* as published by the Free Software Foundation. |
12
|
|
|
* |
13
|
|
|
* This program is distributed in the hope that it will be useful, |
14
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16
|
|
|
* GNU General Public License for more details. |
17
|
|
|
* |
18
|
|
|
* You should have received a copy of the GNU General Public License |
19
|
|
|
* along with this program; if not, you can download one from |
20
|
|
|
* http://www.gnu.org/copyleft/gpl.html. |
21
|
|
|
*/ |
22
|
|
|
namespace ShapeFile; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* ShapeFile class |
26
|
|
|
* |
27
|
|
|
* @package ShapeFile |
28
|
|
|
*/ |
29
|
|
|
class ShapeFile { |
30
|
|
|
public $FileName; |
31
|
|
|
|
32
|
|
|
private $SHPFile = null; |
33
|
|
|
private $SHXFile = null; |
34
|
|
|
private $DBFFile = null; |
35
|
|
|
|
36
|
|
|
public $DBFHeader; |
37
|
|
|
|
38
|
|
|
public $lastError = ''; |
39
|
|
|
|
40
|
|
|
public $boundingBox = array('xmin' => 0.0, 'ymin' => 0.0, 'xmax' => 0.0, 'ymax' => 0.0); |
41
|
|
|
private $fileLength = 0; |
42
|
|
|
public $shapeType = 0; |
43
|
|
|
|
44
|
|
|
public $records; |
45
|
|
|
|
46
|
|
|
private static $shape_names = array( |
47
|
|
|
0 => 'Null Shape', |
48
|
|
|
1 => 'Point', |
49
|
|
|
3 => 'PolyLine', |
50
|
|
|
5 => 'Polygon', |
51
|
|
|
8 => 'MultiPoint', |
52
|
|
|
11 => 'PointZ', |
53
|
|
|
13 => 'PolyLineZ', |
54
|
|
|
15 => 'PolygonZ', |
55
|
|
|
18 => 'MultiPointZ', |
56
|
|
|
21 => 'PointM', |
57
|
|
|
23 => 'PolyLineM', |
58
|
|
|
25 => 'PolygonM', |
59
|
|
|
28 => 'MultiPointM', |
60
|
|
|
31 => 'MultiPatch', |
61
|
|
|
); |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Checks whether dbase manipuations are supported. |
65
|
|
|
* |
66
|
|
|
* @return bool |
67
|
|
|
*/ |
68
|
|
|
public static function supports_dbase() |
69
|
|
|
{ |
70
|
|
|
return extension_loaded('dbase'); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @param integer $shapeType |
75
|
|
|
*/ |
76
|
|
|
public function __construct($shapeType, $boundingBox = array('xmin' => 0.0, 'ymin' => 0.0, 'xmax' => 0.0, 'ymax' => 0.0), $FileName = null) { |
77
|
|
|
$this->shapeType = $shapeType; |
78
|
|
|
$this->boundingBox = $boundingBox; |
79
|
|
|
$this->FileName = $FileName; |
80
|
|
|
$this->fileLength = 50; // The value for file length is the total length of the file in 16-bit words (including the fifty 16-bit words that make up the header). |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @param string $FileName |
85
|
|
|
*/ |
86
|
|
|
public function loadFromFile($FileName) { |
87
|
|
|
if (!empty($FileName)) { |
88
|
|
|
$this->FileName = $FileName; |
89
|
|
|
$result = $this->_openSHPFile(); |
90
|
|
|
} else { |
91
|
|
|
/* We operate on buffer emulated by readSHP / eofSHP */ |
92
|
|
|
$result = true; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
if ($result && ($this->_openDBFFile())) { |
96
|
|
|
if (!$this->_loadHeaders()) { |
97
|
|
|
$this->_closeSHPFile(); |
98
|
|
|
$this->_closeDBFFile(); |
99
|
|
|
return false; |
100
|
|
|
} |
101
|
|
|
if (!$this->_loadRecords()) { |
102
|
|
|
$this->_closeSHPFile(); |
103
|
|
|
$this->_closeDBFFile(); |
104
|
|
|
return false; |
105
|
|
|
} |
106
|
|
|
$this->_closeSHPFile(); |
107
|
|
|
$this->_closeDBFFile(); |
108
|
|
|
return true; |
109
|
|
|
} else { |
110
|
|
|
return false; |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param string|null $FileName Name of file to open |
116
|
|
|
*/ |
117
|
|
|
public function saveToFile($FileName = null) { |
118
|
|
|
if (!is_null($FileName)) { |
119
|
|
|
$this->FileName = $FileName; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if (($this->_openSHPFile(true)) && ($this->_openSHXFile(true)) && ($this->_openDBFFile(true))) { |
123
|
|
|
$this->_saveHeaders(); |
124
|
|
|
$this->_saveRecords(); |
125
|
|
|
$this->_closeSHPFile(); |
126
|
|
|
$this->_closeSHXFile(); |
127
|
|
|
$this->_closeDBFFile(); |
128
|
|
|
} else { |
129
|
|
|
return false; |
130
|
|
|
} |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Generates filename with given extension |
135
|
|
|
* |
136
|
|
|
* @param string $extension Extension to use (including dot) |
137
|
|
|
* |
138
|
|
|
* @return string |
139
|
|
|
*/ |
140
|
|
|
private function _getFilename($extension) |
141
|
|
|
{ |
142
|
|
|
return str_replace('.*', $extension, $this->FileName); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Updates bounding box based on SHPData |
147
|
|
|
* |
148
|
|
|
* @param string $type Type of box |
149
|
|
|
* @param array $data ShapeRecord SHPData |
150
|
|
|
* |
151
|
|
|
* @return void |
152
|
|
|
*/ |
153
|
|
|
private function updateBBox($type, $data) |
154
|
|
|
{ |
155
|
|
|
$min = $type.'min'; |
156
|
|
|
$max = $type.'max'; |
157
|
|
|
|
158
|
|
|
if (!isset($this->boundingBox[$min]) || $this->boundingBox[$min] == 0.0 || ($this->boundingBox[$min] > $data[$min])) { |
|
|
|
|
159
|
|
|
$this->boundingBox[$min] = $data[$min]; |
160
|
|
|
} |
161
|
|
|
if (!isset($this->boundingBox[$max]) || $this->boundingBox[$max] == 0.0 || ($this->boundingBox[$max] < $data[$max])) { |
162
|
|
|
$this->boundingBox[$max] = $data[$max]; |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @param ShapeRecord $record |
168
|
|
|
*/ |
169
|
|
|
public function addRecord($record) { |
170
|
|
|
if ((isset($this->DBFHeader)) && (is_array($this->DBFHeader))) { |
171
|
|
|
$record->updateDBFInfo($this->DBFHeader); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
$this->fileLength += ($record->getContentLength() + 4); |
175
|
|
|
$this->records[] = $record; |
176
|
|
|
$this->records[count($this->records) - 1]->recordNumber = count($this->records); |
177
|
|
|
|
178
|
|
|
$this->updateBBox('x', $record->SHPData); |
179
|
|
|
$this->updateBBox('y', $record->SHPData); |
180
|
|
|
|
181
|
|
|
if (in_array($this->shapeType, array(11, 13, 15, 18, 21, 23, 25, 28))) { |
182
|
|
|
$this->updateBBox('m', $record->SHPData); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
if (in_array($this->shapeType, array(11, 13, 15, 18))) { |
186
|
|
|
$this->updateBBox('z', $record->SHPData); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return (count($this->records) - 1); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* @param integer $index |
194
|
|
|
*/ |
195
|
|
|
public function deleteRecord($index) { |
196
|
|
|
if (isset($this->records[$index])) { |
197
|
|
|
$this->fileLength -= ($this->records[$index]->getContentLength() + 4); |
198
|
|
|
$count = count($this->records) - 1; |
199
|
|
|
for ($i = $index; $i < $count; $i++) { |
200
|
|
|
$this->records[$i] = $this->records[$i + 1]; |
201
|
|
|
} |
202
|
|
|
unset($this->records[count($this->records) - 1]); |
203
|
|
|
$this->_deleteRecordFromDBF($index); |
204
|
|
|
} |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
public function getDBFHeader() { |
208
|
|
|
return $this->DBFHeader; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
public function setDBFHeader($header) { |
212
|
|
|
$this->DBFHeader = $header; |
213
|
|
|
|
214
|
|
|
$count = count($this->records); |
215
|
|
|
for ($i = 0; $i < $count; $i++) { |
216
|
|
|
$this->records[$i]->updateDBFInfo($header); |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
public function getIndexFromDBFData($field, $value) { |
221
|
|
|
$result = -1; |
222
|
|
|
$count = count($this->records) - 1; |
223
|
|
|
for ($i = 0; $i < $count; $i++) { |
224
|
|
|
if (isset($this->records[$i]->DBFData[$field]) && (strtoupper($this->records[$i]->DBFData[$field]) == strtoupper($value))) { |
225
|
|
|
$result = $i; |
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
return $result; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
private function _loadDBFHeader() { |
233
|
|
|
$DBFFile = fopen($this->_getFilename('.dbf'), 'r'); |
234
|
|
|
|
235
|
|
|
$result = array(); |
236
|
|
|
$i = 1; |
237
|
|
|
$inHeader = true; |
238
|
|
|
|
239
|
|
|
while ($inHeader) { |
240
|
|
|
if (!feof($DBFFile)) { |
241
|
|
|
$buff32 = fread($DBFFile, 32); |
242
|
|
|
if ($i > 1) { |
243
|
|
|
if (substr($buff32, 0, 1) == chr(13)) { |
244
|
|
|
$inHeader = false; |
245
|
|
|
} else { |
246
|
|
|
$pos = strpos(substr($buff32, 0, 10), chr(0)); |
247
|
|
|
$pos = ($pos == 0 ? 10 : $pos); |
248
|
|
|
|
249
|
|
|
$fieldName = substr($buff32, 0, $pos); |
250
|
|
|
$fieldType = substr($buff32, 11, 1); |
251
|
|
|
$fieldLen = ord(substr($buff32, 16, 1)); |
252
|
|
|
$fieldDec = ord(substr($buff32, 17, 1)); |
253
|
|
|
|
254
|
|
|
array_push($result, array($fieldName, $fieldType, $fieldLen, $fieldDec)); |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
$i++; |
258
|
|
|
} else { |
259
|
|
|
$inHeader = false; |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
fclose($DBFFile); |
264
|
|
|
return($result); |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
private function _deleteRecordFromDBF($index) { |
268
|
|
|
if (@dbase_delete_record($this->DBFFile, $index)) { |
269
|
|
|
dbase_pack($this->DBFFile); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
private function _loadHeaders() { |
274
|
|
|
if (Util::loadData('N', $this->readSHP(4)) != 9994) { |
275
|
|
|
$this->setError('Not a SHP file (file code mismatch)'); |
276
|
|
|
return false; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/* Skip 20 unused bytes */ |
280
|
|
|
$this->readSHP(20); |
281
|
|
|
|
282
|
|
|
$this->fileLength = Util::loadData('N', $this->readSHP(4)); |
283
|
|
|
|
284
|
|
|
/* We currently ignore version */ |
285
|
|
|
$this->readSHP(4); |
286
|
|
|
|
287
|
|
|
$this->shapeType = Util::loadData('V', $this->readSHP(4)); |
288
|
|
|
|
289
|
|
|
$this->boundingBox = array(); |
290
|
|
|
$this->boundingBox['xmin'] = Util::loadData('d', $this->readSHP(8)); |
291
|
|
|
$this->boundingBox['ymin'] = Util::loadData('d', $this->readSHP(8)); |
292
|
|
|
$this->boundingBox['xmax'] = Util::loadData('d', $this->readSHP(8)); |
293
|
|
|
$this->boundingBox['ymax'] = Util::loadData('d', $this->readSHP(8)); |
294
|
|
|
$this->boundingBox['zmin'] = Util::loadData('d', $this->readSHP(8)); |
295
|
|
|
$this->boundingBox['zmax'] = Util::loadData('d', $this->readSHP(8)); |
296
|
|
|
$this->boundingBox['mmin'] = Util::loadData('d', $this->readSHP(8)); |
297
|
|
|
$this->boundingBox['mmax'] = Util::loadData('d', $this->readSHP(8)); |
298
|
|
|
|
299
|
|
|
if (ShapeFile::supports_dbase()) { |
300
|
|
|
$this->DBFHeader = $this->_loadDBFHeader(); |
301
|
|
|
} |
302
|
|
|
return true; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
private function _saveHeaders() { |
306
|
|
|
fwrite($this->SHPFile, pack('NNNNNN', 9994, 0, 0, 0, 0, 0)); |
307
|
|
|
fwrite($this->SHPFile, pack('N', $this->fileLength)); |
308
|
|
|
fwrite($this->SHPFile, pack('V', 1000)); |
309
|
|
|
fwrite($this->SHPFile, pack('V', $this->shapeType)); |
310
|
|
|
fwrite($this->SHPFile, Util::packDouble($this->boundingBox['xmin'])); |
311
|
|
|
fwrite($this->SHPFile, Util::packDouble($this->boundingBox['ymin'])); |
312
|
|
|
fwrite($this->SHPFile, Util::packDouble($this->boundingBox['xmax'])); |
313
|
|
|
fwrite($this->SHPFile, Util::packDouble($this->boundingBox['ymax'])); |
314
|
|
|
fwrite($this->SHPFile, Util::packDouble(isset($this->boundingBox['zmin']) ? $this->boundingBox['zmin'] : 0)); |
315
|
|
|
fwrite($this->SHPFile, Util::packDouble(isset($this->boundingBox['zmax']) ? $this->boundingBox['zmax'] : 0)); |
316
|
|
|
fwrite($this->SHPFile, Util::packDouble(isset($this->boundingBox['mmin']) ? $this->boundingBox['mmin'] : 0)); |
317
|
|
|
fwrite($this->SHPFile, Util::packDouble(isset($this->boundingBox['mmax']) ? $this->boundingBox['mmax'] : 0)); |
318
|
|
|
|
319
|
|
|
fwrite($this->SHXFile, pack('NNNNNN', 9994, 0, 0, 0, 0, 0)); |
320
|
|
|
fwrite($this->SHXFile, pack('N', 50 + 4 * count($this->records))); |
321
|
|
|
fwrite($this->SHXFile, pack('V', 1000)); |
322
|
|
|
fwrite($this->SHXFile, pack('V', $this->shapeType)); |
323
|
|
|
fwrite($this->SHXFile, Util::packDouble($this->boundingBox['xmin'])); |
324
|
|
|
fwrite($this->SHXFile, Util::packDouble($this->boundingBox['ymin'])); |
325
|
|
|
fwrite($this->SHXFile, Util::packDouble($this->boundingBox['xmax'])); |
326
|
|
|
fwrite($this->SHXFile, Util::packDouble($this->boundingBox['ymax'])); |
327
|
|
|
fwrite($this->SHXFile, Util::packDouble(isset($this->boundingBox['zmin']) ? $this->boundingBox['zmin'] : 0)); |
328
|
|
|
fwrite($this->SHXFile, Util::packDouble(isset($this->boundingBox['zmax']) ? $this->boundingBox['zmax'] : 0)); |
329
|
|
|
fwrite($this->SHXFile, Util::packDouble(isset($this->boundingBox['mmin']) ? $this->boundingBox['mmin'] : 0)); |
330
|
|
|
fwrite($this->SHXFile, Util::packDouble(isset($this->boundingBox['mmax']) ? $this->boundingBox['mmax'] : 0)); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
private function _loadRecords() { |
334
|
|
|
/* Need to start at offset 100 */ |
335
|
|
|
while (!$this->eofSHP()) { |
336
|
|
|
$record = new ShapeRecord(-1); |
337
|
|
|
$record->loadFromFile($this, $this->SHPFile, $this->DBFFile); |
338
|
|
|
if ($record->lastError != '') { |
339
|
|
|
$this->setError($record->lastError); |
340
|
|
|
return false; |
341
|
|
|
} |
342
|
|
|
if (($record->shapeType === false || $record->shapeType === '') && $this->eofSHP()) { |
343
|
|
|
break; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
$this->records[] = $record; |
347
|
|
|
} |
348
|
|
|
return true; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
private function _saveRecords() { |
352
|
|
|
if (!ShapeFile::supports_dbase()) { |
353
|
|
|
return; |
354
|
|
|
} |
355
|
|
|
$dbf_name = $this->_getFilename('.dbf'); |
356
|
|
|
if (file_exists($dbf_name)) { |
357
|
|
|
unlink($dbf_name); |
358
|
|
|
} |
359
|
|
|
if (!($this->DBFFile = @dbase_create($dbf_name, $this->DBFHeader))) { |
|
|
|
|
360
|
|
|
$this->setError(sprintf('It wasn\'t possible to create the DBase file "%s"', $dbf_name)); |
361
|
|
|
return false; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
$offset = 50; |
365
|
|
|
if (is_array($this->records) && (count($this->records) > 0)) { |
366
|
|
|
foreach ($this->records as $index => $record) { |
367
|
|
|
//Save the record to the .shp file |
368
|
|
|
$record->saveToFile($this->SHPFile, $this->DBFFile, $index + 1); |
369
|
|
|
|
370
|
|
|
//Save the record to the .shx file |
371
|
|
|
fwrite($this->SHXFile, pack('N', $offset)); |
372
|
|
|
fwrite($this->SHXFile, pack('N', $record->getContentLength())); |
373
|
|
|
$offset += (4 + $record->getContentLength()); |
374
|
|
|
} |
375
|
|
|
} |
376
|
|
|
dbase_pack($this->DBFFile); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
private function _openFile($toWrite, $extension, $name) { |
380
|
|
|
$shp_name = $this->_getFilename($extension); |
381
|
|
|
$result = @fopen($shp_name, ($toWrite ? 'wb+' : 'rb')); |
382
|
|
|
if (!$result) { |
383
|
|
|
$this->setError(sprintf('It wasn\'t possible to open the %s file "%s"', $name, $shp_name)); |
384
|
|
|
return false; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
return $result; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
private function _openSHPFile($toWrite = false) { |
391
|
|
|
$this->SHPFile = $this->_openFile($toWrite, '.shp', 'Shape'); |
392
|
|
|
if (!$this->SHPFile) { |
393
|
|
|
return false; |
394
|
|
|
} |
395
|
|
|
return true; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
private function _closeSHPFile() { |
399
|
|
|
if ($this->SHPFile) { |
400
|
|
|
fclose($this->SHPFile); |
401
|
|
|
$this->SHPFile = null; |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
private function _openSHXFile($toWrite = false) { |
406
|
|
|
$this->SHXFile = $this->_openFile($toWrite, '.shx', 'Index'); |
407
|
|
|
if (!$this->SHXFile) { |
408
|
|
|
return false; |
409
|
|
|
} |
410
|
|
|
return true; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
private function _closeSHXFile() { |
414
|
|
|
if ($this->SHXFile) { |
415
|
|
|
fclose($this->SHXFile); |
416
|
|
|
$this->SHXFile = null; |
417
|
|
|
} |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* Loads DBF file if supported |
422
|
|
|
* |
423
|
|
|
* @return bool |
424
|
|
|
*/ |
425
|
|
|
private function _openDBFFile($toWrite = false) { |
426
|
|
|
if (!ShapeFile::supports_dbase()) { |
427
|
|
|
return true; |
428
|
|
|
} |
429
|
|
|
$dbf_name = $this->_getFilename('.dbf'); |
430
|
|
|
$checkFunction = $toWrite ? 'is_writable' : 'is_readable'; |
431
|
|
|
if (($toWrite) && (!file_exists($dbf_name))) { |
432
|
|
|
if (!@dbase_create($dbf_name, $this->DBFHeader)) { |
|
|
|
|
433
|
|
|
$this->setError(sprintf('It wasn\'t possible to create the DBase file "%s"', $dbf_name)); |
434
|
|
|
return false; |
435
|
|
|
} |
436
|
|
|
} |
437
|
|
|
if ($checkFunction($dbf_name)) { |
438
|
|
|
$this->DBFFile = @dbase_open($dbf_name, ($toWrite ? 2 : 0)); |
439
|
|
|
if (!$this->DBFFile) { |
440
|
|
|
$this->setError(sprintf('It wasn\'t possible to open the DBase file "%s"', $dbf_name)); |
441
|
|
|
return false; |
442
|
|
|
} |
443
|
|
|
} else { |
444
|
|
|
$this->setError(sprintf('It wasn\'t possible to find the DBase file "%s"', $dbf_name)); |
445
|
|
|
return false; |
446
|
|
|
} |
447
|
|
|
return true; |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
private function _closeDBFFile() { |
451
|
|
|
if ($this->DBFFile) { |
452
|
|
|
dbase_close($this->DBFFile); |
453
|
|
|
$this->DBFFile = null; |
454
|
|
|
} |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* Sets error message |
459
|
|
|
* |
460
|
|
|
* @param string $error |
461
|
|
|
* |
462
|
|
|
* @return void |
463
|
|
|
*/ |
464
|
|
|
public function setError($error) { |
465
|
|
|
$this->lastError = $error; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* Reads given number of bytes from SHP file |
470
|
|
|
* |
471
|
|
|
* @param integer $bytes |
472
|
|
|
* |
473
|
|
|
* @return string |
474
|
|
|
*/ |
475
|
|
|
public function readSHP($bytes) |
476
|
|
|
{ |
477
|
|
|
return fread($this->SHPFile, $bytes); |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
/** |
481
|
|
|
* Checks whether file is at EOF |
482
|
|
|
* |
483
|
|
|
* @return bool |
484
|
|
|
*/ |
485
|
|
|
public function eofSHP() |
486
|
|
|
{ |
487
|
|
|
return feof($this->SHPFile); |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
/** |
491
|
|
|
* Returns shape name |
492
|
|
|
* |
493
|
|
|
* @return string |
494
|
|
|
*/ |
495
|
|
|
public function getShapeName() |
496
|
|
|
{ |
497
|
|
|
return ShapeFile::nameShape($this->shapeType); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Returns shape name |
502
|
|
|
* |
503
|
|
|
* @param integer $type |
504
|
|
|
* |
505
|
|
|
* @return string |
506
|
|
|
*/ |
507
|
|
|
public static function nameShape($type) |
508
|
|
|
{ |
509
|
|
|
if (isset(self::$shape_names[$type])) { |
510
|
|
|
return self::$shape_names[$type]; |
511
|
|
|
} |
512
|
|
|
return sprintf('Shape %d', $type); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* Check whether file contains measure data. |
517
|
|
|
* |
518
|
|
|
* For some reason this is distinguished by zero bouding box in the |
519
|
|
|
* specification. |
520
|
|
|
* |
521
|
|
|
* @return bool |
522
|
|
|
*/ |
523
|
|
|
public function hasMeasure() |
524
|
|
|
{ |
525
|
|
|
return $this->boundingBox['mmin'] != 0 || $this->boundingBox['mmax'] != 0; |
526
|
|
|
} |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.