$points Points (Point Cloud) * * @return array * * @since 1.0.0 */ public static function createConvexHull(array $points) : array { $count = \count($points); if ($count < 3) { return []; } $min = 1; $points = \array_merge([null], $points); for ($i = 2; $i < $count; ++$i) { if ($points[$i]['y'] < $points[$min]['y'] || ($points[$i]['y'] == $points[$min]['y'] && $points[$i]['x'] < $points[$min]['x'])) { $min = $i; } } $temp = $points[1]; $points[1] = $points[$min]; $points[$min] = $temp; $c = $points[1]; $subpoints = \array_slice($points, 2, $count); \usort($subpoints, function (array $a, array $b) use ($c) : bool { return atan2($a['y'] - $c['y'], $a['x'] - $c['x']) < atan2( $b['y'] - $c['y'], $b['x'] - $c['x']); } ); $points = \array_merge([$points[0], $points[1]], $subpoints); $points[0] = $points[$count]; $size = 1; for ($i = 2; $i <= $count; ++$i) { while (self::ccw($points[$size - 1], $points[$size], $points[$i]) <= 0) { if ($size > 1) { --$size; } elseif ($i === $count) { break; } else { ++$i; } } $temp = $points[$i]; $points[$size + 1] = $points[$i]; $points[$i] = $points[$size + 1]; ++$size; } $hull = []; for ($i = 1; $i <= $size; ++$i) { $hull[] = $points[$i]; } return $hull; } public static function ccw(array $a, array $b, array $c) { return (($b['x'] - $a['x']) * ($c['y'] - $a['y']) - ($b['y'] - $a['y']) * ($c['x'] - $a['x'])); } }