PocketMine-MP 5.33.2 git-1133d49c924b4358c79d44eeb97dcbf56cb4d1eb
Loading...
Searching...
No Matches
Vector3.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20*/
21
22declare(strict_types=1);
23
24namespace pocketmine\math;
25
26use function abs;
27use function ceil;
28use function floatval;
29use function floor;
30use function iterator_to_array;
31use function max;
32use function min;
33use function round;
34use function sqrt;
35use const PHP_ROUND_HALF_UP;
36
37readonly class Vector3{
38 public function __construct(
39 public float|int $x,
40 public float|int $y,
41 public float|int $z
42 ){}
43
44 public static function zero() : Vector3{
45 //TODO: make this reuse a single object, once Vector3 becomes immutable
46 return new self(0, 0, 0);
47 }
48
49 public function getX() : float|int{
50 return $this->x;
51 }
52
53 public function getY() : float|int{
54 return $this->y;
55 }
56
57 public function getZ() : float|int{
58 return $this->z;
59 }
60
61 public function getFloorX() : int{
62 return (int) floor($this->x);
63 }
64
65 public function getFloorY() : int{
66 return (int) floor($this->y);
67 }
68
69 public function getFloorZ() : int{
70 return (int) floor($this->z);
71 }
72
73 public function add(float|int $x, float|int $y, float|int $z) : Vector3{
74 return new Vector3($this->x + $x, $this->y + $y, $this->z + $z);
75 }
76
77 public function addVector(Vector3 $v) : Vector3{
78 return $this->add($v->x, $v->y, $v->z);
79 }
80
81 public function subtract(float|int $x, float|int $y, float|int $z) : Vector3{
82 return $this->add(-$x, -$y, -$z);
83 }
84
85 public function subtractVector(Vector3 $v) : Vector3{
86 return $this->add(-$v->x, -$v->y, -$v->z);
87 }
88
89 public function multiply(float $number) : Vector3{
90 return new Vector3($this->x * $number, $this->y * $number, $this->z * $number);
91 }
92
93 public function divide(float $number) : Vector3{
94 return new Vector3($this->x / $number, $this->y / $number, $this->z / $number);
95 }
96
97 public function ceil() : Vector3{
98 return new Vector3((int) ceil($this->x), (int) ceil($this->y), (int) ceil($this->z));
99 }
100
101 public function floor() : Vector3{
102 return new Vector3((int) floor($this->x), (int) floor($this->y), (int) floor($this->z));
103 }
104
108 public function round(int $precision = 0, int $mode = PHP_ROUND_HALF_UP) : Vector3{
109 return $precision > 0 ?
110 new Vector3(round($this->x, $precision, $mode), round($this->y, $precision, $mode), round($this->z, $precision, $mode)) :
111 new Vector3((int) round($this->x, $precision, $mode), (int) round($this->y, $precision, $mode), (int) round($this->z, $precision, $mode));
112 }
113
114 public function abs() : Vector3{
115 return new Vector3(abs($this->x), abs($this->y), abs($this->z));
116 }
117
121 public function getSide(Facing $side, int $step = 1){
122 [$offsetX, $offsetY, $offsetZ] = Facing::OFFSET[$side->value] ?? [0, 0, 0];
123
124 return $this->add($offsetX * $step, $offsetY * $step, $offsetZ * $step);
125 }
126
130 public function down(int $step = 1){
131 return $this->getSide(Facing::DOWN, $step);
132 }
133
137 public function up(int $step = 1){
138 return $this->getSide(Facing::UP, $step);
139 }
140
144 public function north(int $step = 1){
145 return $this->getSide(Facing::NORTH, $step);
146 }
147
151 public function south(int $step = 1){
152 return $this->getSide(Facing::SOUTH, $step);
153 }
154
158 public function west(int $step = 1){
159 return $this->getSide(Facing::WEST, $step);
160 }
161
165 public function east(int $step = 1){
166 return $this->getSide(Facing::EAST, $step);
167 }
168
177 public function sides(int $step = 1) : \Generator{
178 foreach(Facing::ALL as $facing){
179 yield $facing->value => $this->getSide($facing, $step);
180 }
181 }
182
188 public function sidesArray(bool $keys = false, int $step = 1) : array{
189 return iterator_to_array($this->sides($step), $keys);
190 }
191
198 public function sidesAroundAxis(Axis $axis, int $step = 1) : \Generator{
199 foreach(Facing::ALL as $facing){
200 if(Facing::axis($facing) !== $axis){
201 yield $facing->value => $this->getSide($facing, $step);
202 }
203 }
204 }
205
209 public function asVector3() : Vector3{
210 return new Vector3($this->x, $this->y, $this->z);
211 }
212
213 public function distance(Vector3 $pos) : float{
214 return sqrt($this->distanceSquared($pos));
215 }
216
217 public function distanceSquared(Vector3 $pos) : float{
218 $dx = $this->x - $pos->x;
219 $dy = $this->y - $pos->y;
220 $dz = $this->z - $pos->z;
221 return ($dx * $dx) + ($dy * $dy) + ($dz * $dz);
222 }
223
224 public function length() : float{
225 return sqrt($this->lengthSquared());
226 }
227
228 public function lengthSquared() : float{
229 return $this->x * $this->x + $this->y * $this->y + $this->z * $this->z;
230 }
231
232 public function normalize() : Vector3{
233 $len = $this->lengthSquared();
234 if($len > 0){
235 return $this->divide(sqrt($len));
236 }
237
238 return new Vector3(0, 0, 0);
239 }
240
241 public function dot(Vector3 $v) : float{
242 return $this->x * $v->x + $this->y * $v->y + $this->z * $v->z;
243 }
244
245 public function cross(Vector3 $v) : Vector3{
246 return new Vector3(
247 $this->y * $v->z - $this->z * $v->y,
248 $this->z * $v->x - $this->x * $v->z,
249 $this->x * $v->y - $this->y * $v->x
250 );
251 }
252
253 public function equals(Vector3 $v) : bool{
254 return
255 floatval($this->x) === floatval($v->x) and
256 floatval($this->y) === floatval($v->y) and
257 floatval($this->z) === floatval($v->z);
258 }
259
264 public function getIntermediateWithXValue(Vector3 $v, float $x) : ?Vector3{
265 $xDiff = $v->x - $this->x;
266 if(($xDiff * $xDiff) < 0.0000001){
267 return null;
268 }
269
270 $f = ($x - $this->x) / $xDiff;
271
272 if($f < 0 or $f > 1){
273 return null;
274 }else{
275 return new Vector3($x, $this->y + ($v->y - $this->y) * $f, $this->z + ($v->z - $this->z) * $f);
276 }
277 }
278
283 public function getIntermediateWithYValue(Vector3 $v, float $y) : ?Vector3{
284 $yDiff = $v->y - $this->y;
285 if(($yDiff * $yDiff) < 0.0000001){
286 return null;
287 }
288
289 $f = ($y - $this->y) / $yDiff;
290
291 if($f < 0 or $f > 1){
292 return null;
293 }else{
294 return new Vector3($this->x + ($v->x - $this->x) * $f, $y, $this->z + ($v->z - $this->z) * $f);
295 }
296 }
297
302 public function getIntermediateWithZValue(Vector3 $v, float $z) : ?Vector3{
303 $zDiff = $v->z - $this->z;
304 if(($zDiff * $zDiff) < 0.0000001){
305 return null;
306 }
307
308 $f = ($z - $this->z) / $zDiff;
309
310 if($f < 0 or $f > 1){
311 return null;
312 }else{
313 return new Vector3($this->x + ($v->x - $this->x) * $f, $this->y + ($v->y - $this->y) * $f, $z);
314 }
315 }
316
317 public function __toString(){
318 return "Vector3(x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")";
319 }
320
326 public function withComponents(float|int|null $x, float|int|null $y, float|int|null $z) : Vector3{
327 if($x !== null || $y !== null || $z !== null){
328 return new self($x ?? $this->x, $y ?? $this->y, $z ?? $this->z);
329 }
330 return $this;
331 }
332
338 public static function maxComponents(Vector3 $vector, Vector3 ...$vectors) : Vector3{
339 $x = $vector->x;
340 $y = $vector->y;
341 $z = $vector->z;
342 foreach($vectors as $position){
343 $x = max($x, $position->x);
344 $y = max($y, $position->y);
345 $z = max($z, $position->z);
346 }
347 return new Vector3($x, $y, $z);
348 }
349
355 public static function minComponents(Vector3 $vector, Vector3 ...$vectors) : Vector3{
356 $x = $vector->x;
357 $y = $vector->y;
358 $z = $vector->z;
359 foreach($vectors as $position){
360 $x = min($x, $position->x);
361 $y = min($y, $position->y);
362 $z = min($z, $position->z);
363 }
364 return new Vector3($x, $y, $z);
365 }
366
367 public static function sum(Vector3 ...$vector3s) : Vector3{
368 $x = $y = $z = 0;
369 foreach($vector3s as $vector3){
370 $x += $vector3->x;
371 $y += $vector3->y;
372 $z += $vector3->z;
373 }
374 return new Vector3($x, $y, $z);
375 }
376}
getIntermediateWithZValue(Vector3 $v, float $z)
Definition Vector3.php:302
getIntermediateWithXValue(Vector3 $v, float $x)
Definition Vector3.php:264
getSide(Facing $side, int $step=1)
Definition Vector3.php:121
getIntermediateWithYValue(Vector3 $v, float $y)
Definition Vector3.php:283
sidesArray(bool $keys=false, int $step=1)
Definition Vector3.php:188
round(int $precision=0, int $mode=PHP_ROUND_HALF_UP)
Definition Vector3.php:108
withComponents(float|int|null $x, float|int|null $y, float|int|null $z)
Definition Vector3.php:326
static maxComponents(Vector3 $vector, Vector3 ... $vectors)
Definition Vector3.php:338
sidesAroundAxis(Axis $axis, int $step=1)
Definition Vector3.php:198
static minComponents(Vector3 $vector, Vector3 ... $vectors)
Definition Vector3.php:355