xref: /plugin/aichat/vendor/bdelespierre/php-kmeans/src/KMeans/Point.php (revision 3379af09b7ec10f96a8d4f23b1563bd7f9ae79ac)
1*3379af09SAndreas Gohr<?php
2*3379af09SAndreas Gohr
3*3379af09SAndreas Gohr/**
4*3379af09SAndreas Gohr * This file is part of PHP K-Means
5*3379af09SAndreas Gohr *
6*3379af09SAndreas Gohr * Copyright (c) 2014 Benjamin Delespierre
7*3379af09SAndreas Gohr *
8*3379af09SAndreas Gohr * Permission is hereby granted, free of charge, to any person obtaining a copy
9*3379af09SAndreas Gohr * of this software and associated documentation files (the "Software"), to deal
10*3379af09SAndreas Gohr * in the Software without restriction, including without limitation the rights
11*3379af09SAndreas Gohr * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*3379af09SAndreas Gohr * copies of the Software, and to permit persons to whom the Software is furnished
13*3379af09SAndreas Gohr * to do so, subject to the following conditions:
14*3379af09SAndreas Gohr *
15*3379af09SAndreas Gohr * The above copyright notice and this permission notice shall be included in all
16*3379af09SAndreas Gohr * copies or substantial portions of the Software.
17*3379af09SAndreas Gohr *
18*3379af09SAndreas Gohr * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*3379af09SAndreas Gohr * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*3379af09SAndreas Gohr * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21*3379af09SAndreas Gohr * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*3379af09SAndreas Gohr * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*3379af09SAndreas Gohr * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24*3379af09SAndreas Gohr * THE SOFTWARE.
25*3379af09SAndreas Gohr */
26*3379af09SAndreas Gohr
27*3379af09SAndreas Gohrnamespace KMeans;
28*3379af09SAndreas Gohr
29*3379af09SAndreas Gohrclass Point implements \ArrayAccess
30*3379af09SAndreas Gohr{
31*3379af09SAndreas Gohr    protected $space;
32*3379af09SAndreas Gohr    protected $dimention;
33*3379af09SAndreas Gohr    protected $coordinates;
34*3379af09SAndreas Gohr
35*3379af09SAndreas Gohr    public function __construct(Space $space, array $coordinates)
36*3379af09SAndreas Gohr    {
37*3379af09SAndreas Gohr        $this->space       = $space;
38*3379af09SAndreas Gohr        $this->dimention   = $space->getDimention();
39*3379af09SAndreas Gohr        $this->coordinates = $coordinates;
40*3379af09SAndreas Gohr    }
41*3379af09SAndreas Gohr
42*3379af09SAndreas Gohr    public function toArray(): array
43*3379af09SAndreas Gohr    {
44*3379af09SAndreas Gohr        return [
45*3379af09SAndreas Gohr            'coordinates' => $this->coordinates,
46*3379af09SAndreas Gohr            'data' => isset($this->space[$this]) ? $this->space[$this] : null,
47*3379af09SAndreas Gohr        ];
48*3379af09SAndreas Gohr    }
49*3379af09SAndreas Gohr
50*3379af09SAndreas Gohr    public function getDistanceWith(self $point, bool $precise = true): float
51*3379af09SAndreas Gohr    {
52*3379af09SAndreas Gohr        if ($point->space !== $this->space) {
53*3379af09SAndreas Gohr            throw new \LogicException("can only calculate distances from points in the same space");
54*3379af09SAndreas Gohr        }
55*3379af09SAndreas Gohr
56*3379af09SAndreas Gohr        $distance = 0;
57*3379af09SAndreas Gohr        for ($n = 0; $n < $this->dimention; $n++) {
58*3379af09SAndreas Gohr            $difference = $this->coordinates[$n] - $point->coordinates[$n];
59*3379af09SAndreas Gohr            $distance  += $difference * $difference;
60*3379af09SAndreas Gohr        }
61*3379af09SAndreas Gohr
62*3379af09SAndreas Gohr        return $precise ? sqrt($distance) : $distance;
63*3379af09SAndreas Gohr    }
64*3379af09SAndreas Gohr
65*3379af09SAndreas Gohr    public function getClosest(iterable $points): ?Point
66*3379af09SAndreas Gohr    {
67*3379af09SAndreas Gohr        $minDistance = PHP_INT_MAX;
68*3379af09SAndreas Gohr        $minPoint = null;
69*3379af09SAndreas Gohr        foreach ($points as $point) {
70*3379af09SAndreas Gohr            $distance = $this->getDistanceWith($point, false);
71*3379af09SAndreas Gohr
72*3379af09SAndreas Gohr            if ($distance < $minDistance) {
73*3379af09SAndreas Gohr                $minDistance = $distance;
74*3379af09SAndreas Gohr                $minPoint    = $point;
75*3379af09SAndreas Gohr            }
76*3379af09SAndreas Gohr        }
77*3379af09SAndreas Gohr
78*3379af09SAndreas Gohr        return $minPoint;
79*3379af09SAndreas Gohr    }
80*3379af09SAndreas Gohr
81*3379af09SAndreas Gohr    public function belongsTo(Space $space): bool
82*3379af09SAndreas Gohr    {
83*3379af09SAndreas Gohr        return $this->space === $space;
84*3379af09SAndreas Gohr    }
85*3379af09SAndreas Gohr
86*3379af09SAndreas Gohr    public function getSpace(): Space
87*3379af09SAndreas Gohr    {
88*3379af09SAndreas Gohr        return $this->space;
89*3379af09SAndreas Gohr    }
90*3379af09SAndreas Gohr
91*3379af09SAndreas Gohr    public function getCoordinates(): array
92*3379af09SAndreas Gohr    {
93*3379af09SAndreas Gohr        return $this->coordinates;
94*3379af09SAndreas Gohr    }
95*3379af09SAndreas Gohr
96*3379af09SAndreas Gohr    public function offsetExists($offset): bool
97*3379af09SAndreas Gohr    {
98*3379af09SAndreas Gohr        return isset($this->coordinates[$offset]);
99*3379af09SAndreas Gohr    }
100*3379af09SAndreas Gohr
101*3379af09SAndreas Gohr    public function offsetGet($offset)
102*3379af09SAndreas Gohr    {
103*3379af09SAndreas Gohr        return $this->coordinates[$offset];
104*3379af09SAndreas Gohr    }
105*3379af09SAndreas Gohr
106*3379af09SAndreas Gohr    public function offsetSet($offset, $value): void
107*3379af09SAndreas Gohr    {
108*3379af09SAndreas Gohr        $this->coordinates[$offset] = $value;
109*3379af09SAndreas Gohr    }
110*3379af09SAndreas Gohr
111*3379af09SAndreas Gohr    public function offsetUnset($offset): void
112*3379af09SAndreas Gohr    {
113*3379af09SAndreas Gohr        unset($this->coordinates[$offset]);
114*3379af09SAndreas Gohr    }
115*3379af09SAndreas Gohr}
116