Completed
Push — master ( 0885cd...ef8e35 )
by Antoine
02:22
created

Polygon::getEllipsoid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Geotools library.
5
 *
6
 * (c) Antoine Corcy <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace League\Geotools\Polygon;
13
14
use League\Geotools\BoundingBox\BoundingBox;
15
use League\Geotools\BoundingBox\BoundingBoxInterface;
16
use League\Geotools\Coordinate\Coordinate;
17
use League\Geotools\Coordinate\CoordinateCollection;
18
use League\Geotools\Coordinate\CoordinateInterface;
19
use League\Geotools\Coordinate\Ellipsoid;
20
21
/**
22
 * @author Gabriel Bull <[email protected]>
23
 */
24
class Polygon implements PolygonInterface, \Countable, \IteratorAggregate, \ArrayAccess, \JsonSerializable
25
{
26
    const TYPE = 'POLYGON';
27
28
    /**
29
     * @var CoordinateCollection
30
     */
31
    private $coordinates;
32
33
    /**
34
     * @var BoundingBoxInterface
35
     */
36
    private $boundingBox;
37
38
    /**
39
     * @var boolean
40
     */
41
    private $hasCoordinate = false;
42
43
    /**
44
     * @var integer
45
     */
46
    private $precision = 8;
47
48
    /**
49
     * @param null|array|CoordinateCollection $coordinates
50
     */
51 38
    public function __construct($coordinates = null)
52
    {
53 38
        if (is_array($coordinates) || null === $coordinates) {
54 25
            $this->coordinates = new CoordinateCollection;
55 38
        } elseif ($coordinates instanceof CoordinateCollection) {
56 15
            $this->coordinates = $coordinates;
57 15
            $this->hasCoordinate = $coordinates->count() > 0;
58 15
        } else {
59 2
            throw new \InvalidArgumentException;
60
        }
61
62 38
        $this->boundingBox = new BoundingBox($this);
63
64 38
        if (is_array($coordinates)) {
65 4
            $this->set($coordinates);
66 4
        }
67 38
    }
68
69
    /**
70
     * @return string
71
     */
72
    public function getGeometryType()
73
    {
74
        return self::TYPE;
75
    }
76
77
    /**
78
     * @return Ellipsoid
79
     */
80 17
    public function getEllipsoid()
81
    {
82 17
        return $this->coordinates->getEllipsoid();
83
    }
84
85
    /**
86
     * @return Coordinate
87
     */
88 1
    public function getCoordinate()
89
    {
90 1
        return $this->coordinates->offsetGet(0);
91
    }
92
93
    /**
94
     * @return boolean
95
     */
96 8
    public function isEmpty()
97
    {
98 8
        return !$this->hasCoordinate;
99
    }
100
101
102
    /**
103
     * @param  CoordinateInterface $coordinate
104
     * @return boolean
105
     */
106 4
    public function pointInPolygon(CoordinateInterface $coordinate)
107
    {
108 4
        if (!$this->hasCoordinate) {
109
            return false;
110
        }
111
112 4
        if (!$this->boundingBox->pointInBoundingBox($coordinate)) {
113 2
            return false;
114
        }
115
116 2
        if ($this->pointOnVertex($coordinate)) {
117
            return true;
118
        }
119
120 2
        if ($this->pointOnBoundary($coordinate)) {
121
            return true;
122
        }
123
124 2
        $total = $this->count();
125 2
        $intersections = 0;
126 2
        for ($i = 1; $i < $total; $i++) {
127 2
            $currentVertex = $this->get($i - 1);
128 2
            $nextVertex = $this->get($i);
129
130 2
            if (bccomp(
131 2
                $coordinate->getLatitude(),
132 2
                min($currentVertex->getLatitude(), $nextVertex->getLatitude()),
133 2
                $this->getPrecision()
134 2
            ) === 1 &&
135 2
                bccomp(
136 2
                    $coordinate->getLatitude(),
137 2
                    max($currentVertex->getLatitude(), $nextVertex->getLatitude()),
138 2
                    $this->getPrecision()
139 2
                ) <= 0 &&
140 2
                bccomp(
141 2
                    $coordinate->getLongitude(),
142 2
                    max($currentVertex->getLongitude(), $nextVertex->getLongitude()),
143 2
                    $this->getPrecision()
144 2
                ) <= 0 &&
145 2
                bccomp(
146 2
                    $currentVertex->getLatitude(),
147 2
                    $nextVertex->getLatitude(),
148 2
                    $this->getPrecision()
149 2
                ) !== 0
150 2
            ) {
151
                $xinters =
152 2
                    ($coordinate->getLatitude() - $currentVertex->getLatitude()) *
153 2
                    ($nextVertex->getLongitude() - $currentVertex->getLongitude()) /
154 2
                    ($nextVertex->getLatitude() - $currentVertex->getLatitude()) +
155 2
                    $currentVertex->getLongitude();
156
157 2
                if (bccomp(
158 2
                    $currentVertex->getLongitude(),
159 2
                    $nextVertex->getLongitude(),
160 2
                    $this->getPrecision()
161 2
                ) === 0 ||
162 2
                    bccomp(
163 2
                        $coordinate->getLongitude(),
164 2
                        $xinters,
165 2
                        $this->getPrecision()
166 2
                    ) <= 0
167 2
                ) {
168 2
                    $intersections++;
169 2
                }
170 2
            }
171 2
        }
172
173 2
        if ($intersections % 2 != 0) {
174 2
            return true;
175
        }
176
177
        return false;
178
    }
179
180
    /**
181
     * @param  CoordinateInterface $coordinate
182
     * @return boolean
183
     */
184 6
    public function pointOnBoundary(CoordinateInterface $coordinate)
185
    {
186 6
        $total = $this->count();
187 6
        for ($i = 1; $i <= $total; $i++) {
188 6
            $currentVertex = $this->get($i - 1);
189 6
            $nextVertex = $this->get($i);
190
191 6
            if (null === $nextVertex) {
192 6
                $nextVertex = $this->get(0);
193 6
            }
194
195
            // Check if coordinate is on a horizontal boundary
196 6
            if (bccomp(
197 6
                $currentVertex->getLatitude(),
198 6
                $nextVertex->getLatitude(),
199 6
                $this->getPrecision()
200 6
            ) === 0 &&
201
                bccomp(
202
                    $currentVertex->getLatitude(),
203
                    $coordinate->getLatitude(),
204
                    $this->getPrecision()
205 6
                ) === 0 &&
206
                bccomp(
207
                    $coordinate->getLongitude(),
208
                    min($currentVertex->getLongitude(), $nextVertex->getLongitude()),
209
                    $this->getPrecision()
210 6
                ) === 1 &&
211
                bccomp(
212
                    $coordinate->getLongitude(),
213
                    max($currentVertex->getLongitude(), $nextVertex->getLongitude()),
214
                    $this->getPrecision()
215
                ) === -1
216 6
            ) {
217
                return true;
218
            }
219
220
            // Check if coordinate is on a boundary
221 6
            if (bccomp(
222 6
                $coordinate->getLatitude(),
223 6
                min($currentVertex->getLatitude(), $nextVertex->getLatitude()),
224 6
                $this->getPrecision()
225 6
            ) === 1 &&
226 4
                bccomp(
227 4
                    $coordinate->getLatitude(),
228 4
                    max($currentVertex->getLatitude(), $nextVertex->getLatitude()),
229 4
                    $this->getPrecision()
230 6
                ) <= 0 &&
231 4
                bccomp(
232 4
                    $coordinate->getLongitude(),
233 4
                    max($currentVertex->getLongitude(), $nextVertex->getLongitude()),
234 4
                    $this->getPrecision()
235 6
                ) <= 0 &&
236 4
                bccomp(
237 4
                    $currentVertex->getLatitude(),
238 4
                    $nextVertex->getLatitude(),
239 4
                    $this->getPrecision()
240 4
                ) !== 0
241 6
            ) {
242
                $xinters =
243 4
                    ($coordinate->getLatitude() - $currentVertex->getLatitude()) *
244 4
                    ($nextVertex->getLongitude() - $currentVertex->getLongitude()) /
245 4
                    ($nextVertex->getLatitude() - $currentVertex->getLatitude()) +
246 4
                    $currentVertex->getLongitude();
247
248 4
                if (bccomp($xinters, $coordinate->getLongitude(), $this->getPrecision()) === 0) {
249 2
                    return true;
250
                }
251 4
            }
252 6
        }
253
254 4
        return false;
255
    }
256
257
    /**
258
     * @param  CoordinateInterface $coordinate
259
     * @return boolean
260
     */
261 6
    public function pointOnVertex(CoordinateInterface $coordinate)
262
    {
263 6
        foreach ($this->coordinates as $vertexCoordinate) {
264 6
            if (bccomp(
265 6
                $vertexCoordinate->getLatitude(),
266 6
                $coordinate->getLatitude(),
267 6
                $this->getPrecision()
268 6
            ) === 0 &&
269 4
                bccomp(
270 4
                    $vertexCoordinate->getLongitude(),
271 4
                    $coordinate->getLongitude(),
272 4
                    $this->getPrecision()
273 4
                ) === 0
274 6
            ) {
275 2
                return true;
276
            }
277 6
        }
278
279 4
        return false;
280
    }
281
282
    /**
283
     * {@inheritDoc}
284
     */
285 38
    public function getCoordinates()
286
    {
287 38
        return $this->coordinates;
288
    }
289
290
    /**
291
     * {@inheritDoc}
292
     */
293
    public function setCoordinates(CoordinateCollection $coordinates)
294
    {
295
        $this->coordinates = $coordinates;
296
        $this->boundingBox->setPolygon($this);
297
298
        return $this;
299
    }
300
301
    /**
302
     * @return array
303
     */
304
    public function toArray()
305
    {
306
        return $this->coordinates->toArray();
307
    }
308
309
    /**
310
     * {@inheritDoc}
311
     */
312
    public function jsonSerialize()
313
    {
314
        return $this->coordinates->jsonSerialize();
315
    }
316
317
    /**
318
     * {@inheritDoc}
319
     */
320
    public function offsetExists($offset)
321
    {
322
        return $this->coordinates->offsetExists($offset);
323
    }
324
325
    /**
326
     * {@inheritDoc}
327
     */
328
    public function offsetGet($offset)
329
    {
330
        return $this->coordinates->offsetGet($offset);
331
    }
332
333
    /**
334
     * {@inheritDoc}
335
     */
336
    public function offsetSet($offset, $value)
337
    {
338
        $this->coordinates->offsetSet($offset, $value);
339
        $this->boundingBox->setPolygon($this);
340
    }
341
342
    /**
343
     * {@inheritDoc}
344
     */
345
    public function offsetUnset($offset)
346
    {
347
        $retval = $this->coordinates->offsetUnset($offset);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $retval is correct as $this->coordinates->offsetUnset($offset) (which targets League\Geotools\ArrayCollection::offsetUnset()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
348
        $this->boundingBox->setPolygon($this);
349
        return $retval;
350
    }
351
352
    /**
353
     * {@inheritDoc}
354
     */
355 7
    public function count()
356
    {
357 7
        return $this->coordinates->count();
358
    }
359
360
    /**
361
     * {@inheritDoc}
362
     */
363
    public function getIterator()
364
    {
365
        return $this->coordinates->getIterator();
366
    }
367
368
    /**
369
     * {@inheritDoc}
370
     */
371 7
    public function get($key)
372
    {
373 7
        return $this->coordinates->get($key);
374
    }
375
376
    /**
377
     * {@inheritDoc}
378
     */
379 17
    public function set($key, CoordinateInterface $coordinate = null)
380
    {
381 17
        if (is_array($key)) {
382 17
            $values = $key;
383 17
        } elseif (null !== $coordinate) {
384
            $values = array($key => $coordinate);
385
        } else {
386
            throw new \InvalidArgumentException;
387
        }
388
389 17
        foreach ($values as $key => $value) {
390 17
            if (!$value instanceof CoordinateInterface) {
391 14
                $value = new Coordinate($value);
392 14
            }
393 17
            $this->coordinates->set($key, $value);
394 17
        }
395
396 17
        $this->hasCoordinate = true;
397 17
        $this->boundingBox->setPolygon($this);
398 17
    }
399
400
    /**
401
     * {@inheritDoc}
402
     */
403 1
    public function add(CoordinateInterface $coordinate)
404
    {
405 1
        $retval = $this->coordinates->add($coordinate);
406
407 1
        $this->hasCoordinate = true;
408 1
        $this->boundingBox->setPolygon($this);
409
410 1
        return $retval;
411
    }
412
413
    /**
414
     * {@inheritDoc}
415
     */
416
    public function remove($key)
417
    {
418
        $retval = $this->coordinates->remove($key);
419
420
        if (!count($this->coordinates)) {
421
            $this->hasCoordinate = false;
422
        }
423
        $this->boundingBox->setPolygon($this);
424
425
        return $retval;
426
    }
427
428
    /**
429
     * @return integer
430
     */
431 22
    public function getPrecision()
432
    {
433 22
        return $this->precision;
434
    }
435
436
    /**
437
     * @param  integer $precision
438
     * @return $this
439
     */
440 1
    public function setPrecision($precision)
441
    {
442 1
        $this->boundingBox->setPrecision($precision);
443 1
        $this->precision = $precision;
444
445 1
        return $this;
446
    }
447
448
    /**
449
     * @return BoundingBoxInterface
450
     */
451 2
    public function getBoundingBox()
452
    {
453 2
        return $this->boundingBox;
454
    }
455
456
    /**
457
     * @param  BoundingBoxInterface $boundingBox
458
     * @return $this
459
     */
460
    public function setBoundingBox(BoundingBoxInterface $boundingBox)
461
    {
462
        $this->boundingBox = $boundingBox;
463
464
        return $this;
465
    }
466
}
467