Passed
Push — master ( 58539d...96b0d3 )
by Mark
01:31
created

WKT::extractData()   B

Complexity

Conditions 11
Paths 14

Size

Total Lines 23
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 23
rs 7.3166
c 0
b 0
f 0
cc 11
nc 14
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * WKT (Well Known Text) Adapter
4
 */
5
class WKT extends GeoAdapter
6
{
7
8
  /**
9
   * Read WKT string into geometry objects
10
   *
11
   * @param string $WKT A WKT string
12
   *
13
   * @return Geometry
14
   */
15
  public function read($wkt) {
16
    $wkt = trim($wkt);
17
18
    // If it contains a ';', then it contains additional SRID data
19
    if (strpos($wkt,';')) {
20
      $parts = explode(';', $wkt);
21
      $wkt = $parts[1];
22
      $eparts = explode('=',$parts[0]);
23
      $srid = $eparts[1];
24
    }
25
    else {
26
      $srid = NULL;
27
    }
28
29
    // If geos is installed, then we take a shortcut and let it parse the WKT
30
    if (geoPHP::geosInstalled()) {
31
      $reader = new GEOSWKTReader();
32
      if ($srid) {
33
        $geom = geoPHP::geosToGeometry($reader->read($wkt));
34
        $geom->setSRID($srid);
35
        return $geom;
36
      }
37
      else {
38
        return geoPHP::geosToGeometry($reader->read($wkt));
39
      }
40
    }
41
    $wkt = str_replace(', ', ',', $wkt);
42
43
    // For each geometry type, check to see if we have a match at the
44
    // beginning of the string. If we do, then parse using that type
45
    foreach (geoPHP::geometryList() as $geom_type) {
46
      $wkt_geom = strtoupper($geom_type);
47
      if (strtoupper(substr($wkt, 0, strlen($wkt_geom))) == $wkt_geom) {
48
        $data_string = $this->getDataString($wkt);
49
        $method = 'parse'.$geom_type;
50
51
        if ($srid) {
52
          $geom = $this->$method($data_string);
53
          $geom->setSRID($srid);
54
          return $geom;
55
        }
56
        else {
57
          return $this->$method($data_string);
58
        }
59
60
      }
61
    }
62
  }
63
64
  private function parsePoint($data_string) {
65
    $data_string = $this->trimParens($data_string);
66
67
    // If it's marked as empty, then return an empty point
68
    if ($data_string == 'EMPTY') return new Point();
69
70
    $parts = explode(' ',$data_string);
71
    return new Point($parts[0], $parts[1]);
72
  }
73
74
  private function parseLineString($data_string) {
75
    $data_string = $this->trimParens($data_string);
76
77
    // If it's marked as empty, then return an empty line
78
    if ($data_string == 'EMPTY') return new LineString();
79
80
    $parts = explode(',',$data_string);
81
    $points = array();
82
    foreach ($parts as $part) {
83
      $points[] = $this->parsePoint($part);
84
    }
85
    return new LineString($points);
86
  }
87
88
  private function parsePolygon($data_string) {
89
    $data_string = $this->trimParens($data_string);
90
91
    // If it's marked as empty, then return an empty polygon
92
    if ($data_string == 'EMPTY') return new Polygon();
93
94
    $parts = explode('),(',$data_string);
95
    $lines = array();
96
    foreach ($parts as $part) {
97
      if (!$this->beginsWith($part,'(')) $part = '(' . $part;
98
      if (!$this->endsWith($part,')'))   $part = $part . ')';
99
      $lines[] = $this->parseLineString($part);
100
    }
101
    return new Polygon($lines);
102
  }
103
104
  private function parseMultiPoint($data_string) {
105
    $data_string = $this->trimParens($data_string);
106
107
    // If it's marked as empty, then return an empty MutiPoint
108
    if ($data_string == 'EMPTY') return new MultiPoint();
109
110
    $parts = explode(',',$data_string);
111
    $points = array();
112
    foreach ($parts as $part) {
113
      $points[] = $this->parsePoint($part);
114
    }
115
    return new MultiPoint($points);
116
  }
117
118
  private function parseMultiLineString($data_string) {
119
    $data_string = $this->trimParens($data_string);
120
121
    // If it's marked as empty, then return an empty multi-linestring
122
    if ($data_string == 'EMPTY') return new MultiLineString();
123
124
    $parts = explode('),(',$data_string);
125
    $lines = array();
126
    foreach ($parts as $part) {
127
      // Repair the string if the explode broke it
128
      if (!$this->beginsWith($part,'(')) $part = '(' . $part;
129
      if (!$this->endsWith($part,')'))   $part = $part . ')';
130
      $lines[] = $this->parseLineString($part);
131
    }
132
    return new MultiLineString($lines);
133
  }
134
135
  private function parseMultiPolygon($data_string) {
136
    $data_string = $this->trimParens($data_string);
137
138
    // If it's marked as empty, then return an empty multi-polygon
139
    if ($data_string == 'EMPTY') return new MultiPolygon();
140
141
    $parts = explode(')),((',$data_string);
142
    $polys = array();
143
    foreach ($parts as $part) {
144
      // Repair the string if the explode broke it
145
      if (!$this->beginsWith($part,'((')) $part = '((' . $part;
146
      if (!$this->endsWith($part,'))'))   $part = $part . '))';
147
      $polys[] = $this->parsePolygon($part);
148
    }
149
    return new MultiPolygon($polys);
150
  }
151
152
  private function parseGeometryCollection($data_string) {
153
    $data_string = $this->trimParens($data_string);
154
155
    // If it's marked as empty, then return an empty geom-collection
156
    if ($data_string == 'EMPTY') return new GeometryCollection();
157
158
    $geometries = array();
159
    $matches = array();
160
    $str = preg_replace('/,\s*([A-Za-z])/', '|$1', $data_string);
161
    $components = explode('|', trim($str));
162
163
    foreach ($components as $component) {
164
      $geometries[] = $this->read($component);
165
    }
166
    return new GeometryCollection($geometries);
167
  }
168
169
  protected function getDataString($wkt) {
170
    $first_paren = strpos($wkt, '(');
171
172
    if ($first_paren !== FALSE) {
173
      return substr($wkt, $first_paren);
174
    } elseif (strstr($wkt,'EMPTY')) {
175
      return 'EMPTY';
176
    } else
177
      return FALSE;
178
  }
179
180
  /**
181
   * Trim the parenthesis and spaces
182
   */
183
  protected function trimParens($str) {
184
    $str = trim($str);
185
186
    // We want to only strip off one set of parenthesis
187
    if ($this->beginsWith($str, '(')) {
188
      return substr($str,1,-1);
189
    }
190
    else return $str;
191
  }
192
193
  protected function beginsWith($str, $char) {
194
    if (substr($str,0,strlen($char)) == $char) return TRUE;
195
    else return FALSE;
196
  }
197
198
  protected function endsWith($str, $char) {
199
    if (substr($str,(0 - strlen($char))) == $char) return TRUE;
200
    else return FALSE;
201
  }
202
203
  /**
204
   * Serialize geometries into a WKT string.
205
   *
206
   * @param Geometry $geometry
207
   *
208
   * @return string The WKT string representation of the input geometries
209
   */
210
  public function write(Geometry $geometry) {
211
    // If geos is installed, then we take a shortcut and let it write the WKT
212
    if (geoPHP::geosInstalled()) {
213
      $writer = new GEOSWKTWriter();
214
      $writer->setTrim(TRUE);
215
      return $writer->write($geometry->geos());
216
    }
217
218
    if ($geometry->isEmpty()) {
219
      return strtoupper($geometry->geometryType()).' EMPTY';
220
    }
221
    else if ($data = $this->extractData($geometry)) {
222
      return strtoupper($geometry->geometryType()).' ('.$data.')';
223
    }
224
  }
225
226
  /**
227
   * Extract geometry to a WKT string
228
   *
229
   * @param Geometry $geometry A Geometry object
230
   *
231
   * @return string
232
   */
233
  public function extractData($geometry) {
234
    $parts = array();
235
    switch ($geometry->geometryType()) {
236
      case 'Point':
237
        return $geometry->getX().' '.$geometry->getY();
238
      case 'LineString':
239
        foreach ($geometry->getComponents() as $component) {
240
          $parts[] = $this->extractData($component);
241
        }
242
        return implode(', ', $parts);
243
      case 'Polygon':
244
      case 'MultiPoint':
245
      case 'MultiLineString':
246
      case 'MultiPolygon':
247
        foreach ($geometry->getComponents() as $component) {
248
          $parts[] = '('.$this->extractData($component).')';
249
        }
250
        return implode(', ', $parts);
251
      case 'GeometryCollection':
252
        foreach ($geometry->getComponents() as $component) {
253
          $parts[] = strtoupper($component->geometryType()).' ('.$this->extractData($component).')';
254
        }
255
        return implode(', ', $parts);
256
    }
257
  }
258
}
259