Skip to content

Commit acfaf0e

Browse files
committed
First shot at extracting IntVector3 from Vector3
1 parent 7653a0a commit acfaf0e

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

src/IntVector3.php

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
<?php
2+
3+
/*
4+
* This file is part of pmmp/Math.
5+
* Copyright (c) 2014-2024 PMMP Team <https://github.com/pmmp/Math>
6+
*
7+
* pmmp/Math is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*/
12+
13+
declare(strict_types=1);
14+
15+
namespace pocketmine\math;
16+
17+
use function abs;
18+
use function iterator_to_array;
19+
use function max;
20+
use function min;
21+
use function sqrt;
22+
23+
readonly class IntVector3{
24+
public function __construct(
25+
public int $x,
26+
public int $y,
27+
public int $z
28+
){}
29+
30+
public static function zero() : IntVector3{
31+
//TODO: make this reuse a single object, once Vector3 becomes immutable
32+
return new self(0, 0, 0);
33+
}
34+
35+
public function add(int $x, int $y, int $z) : IntVector3{
36+
return new IntVector3($this->x + $x, $this->y + $y, $this->z + $z);
37+
}
38+
39+
public function addVector(IntVector3 $v) : IntVector3{
40+
return $this->add($v->x, $v->y, $v->z);
41+
}
42+
43+
public function subtract(int $x, int $y, int $z) : IntVector3{
44+
return $this->add(-$x, -$y, -$z);
45+
}
46+
47+
public function subtractVector(IntVector3 $v) : IntVector3{
48+
return $this->add(-$v->x, -$v->y, -$v->z);
49+
}
50+
51+
public function multiply(int $number) : IntVector3{
52+
return new IntVector3($this->x * $number, $this->y * $number, $this->z * $number);
53+
}
54+
55+
public function abs() : IntVector3{
56+
return new IntVector3(abs($this->x), abs($this->y), abs($this->z));
57+
}
58+
59+
/**
60+
* @return IntVector3
61+
*/
62+
public function getSide(Facing $side, int $step = 1){
63+
[$offsetX, $offsetY, $offsetZ] = $side->offset();
64+
65+
return $this->add($offsetX * $step, $offsetY * $step, $offsetZ * $step);
66+
}
67+
68+
/**
69+
* @return IntVector3
70+
*/
71+
public function down(int $step = 1){
72+
return $this->getSide(Facing::DOWN, $step);
73+
}
74+
75+
/**
76+
* @return IntVector3
77+
*/
78+
public function up(int $step = 1){
79+
return $this->getSide(Facing::UP, $step);
80+
}
81+
82+
/**
83+
* @return IntVector3
84+
*/
85+
public function north(int $step = 1){
86+
return $this->getSide(Facing::NORTH, $step);
87+
}
88+
89+
/**
90+
* @return IntVector3
91+
*/
92+
public function south(int $step = 1){
93+
return $this->getSide(Facing::SOUTH, $step);
94+
}
95+
96+
/**
97+
* @return IntVector3
98+
*/
99+
public function west(int $step = 1){
100+
return $this->getSide(Facing::WEST, $step);
101+
}
102+
103+
/**
104+
* @return IntVector3
105+
*/
106+
public function east(int $step = 1){
107+
return $this->getSide(Facing::EAST, $step);
108+
}
109+
110+
/**
111+
* Yields vectors stepped out from this one in all directions.
112+
*
113+
* @param int $step Distance in each direction to shift the vector
114+
*
115+
* @return \Generator|IntVector3[]
116+
* @phpstan-return \Generator<Facing, IntVector3, void, void>
117+
*/
118+
public function sides(int $step = 1) : \Generator{
119+
foreach(Facing::cases() as $facing){
120+
yield $facing => $this->getSide($facing, $step);
121+
}
122+
}
123+
124+
/**
125+
* Same as sides() but returns a pre-populated array instead of Generator.
126+
*
127+
* @return IntVector3[]
128+
*/
129+
public function sidesArray(bool $keys = false, int $step = 1) : array{
130+
return iterator_to_array($this->sides($step), $keys);
131+
}
132+
133+
/**
134+
* Yields vectors stepped out from this one in directions except those on the given axis.
135+
*
136+
* @param Axis $axis Facing directions on this axis will be excluded
137+
*
138+
* @return \Generator|IntVector3[]
139+
* @phpstan-return \Generator<Facing, IntVector3, void, void>
140+
*/
141+
public function sidesAroundAxis(Axis $axis, int $step = 1) : \Generator{
142+
foreach(Facing::cases() as $facing){
143+
if($facing->axis() !== $axis){
144+
yield $facing => $this->getSide($facing, $step);
145+
}
146+
}
147+
}
148+
149+
public function asIntVector3() : IntVector3{
150+
return new self($this->x, $this->y, $this->z);
151+
}
152+
153+
public function distance(IntVector3 $pos) : float{
154+
return sqrt($this->distanceSquared($pos));
155+
}
156+
157+
public function distanceSquared(IntVector3 $pos) : float{
158+
$dx = $this->x - $pos->x;
159+
$dy = $this->y - $pos->y;
160+
$dz = $this->z - $pos->z;
161+
return ($dx * $dx) + ($dy * $dy) + ($dz * $dz);
162+
}
163+
164+
public function length() : float{
165+
return sqrt($this->lengthSquared());
166+
}
167+
168+
public function lengthSquared() : float{
169+
return $this->x * $this->x + $this->y * $this->y + $this->z * $this->z;
170+
}
171+
172+
public function dot(IntVector3 $v) : float{
173+
return $this->x * $v->x + $this->y * $v->y + $this->z * $v->z;
174+
}
175+
176+
public function cross(IntVector3 $v) : IntVector3{
177+
return new IntVector3(
178+
$this->y * $v->z - $this->z * $v->y,
179+
$this->z * $v->x - $this->x * $v->z,
180+
$this->x * $v->y - $this->y * $v->x
181+
);
182+
}
183+
184+
public function equals(IntVector3 $v) : bool{
185+
return $this->x === $v->x && $this->y === $v->y && $this->z === $v->z;
186+
}
187+
188+
public function __toString(){
189+
return "IntVector3(x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")";
190+
}
191+
192+
/**
193+
* Returns a Vector3 with the provided components. If any of the components are null, the values from this
194+
* Vector3 will be filled in instead.
195+
* If no components are overridden (all components are null), the original vector will be returned unchanged.
196+
*/
197+
public function withComponents(?int $x, ?int $y, ?int $z) : IntVector3{
198+
if($x !== null || $y !== null || $z !== null){
199+
return new self($x ?? $this->x, $y ?? $this->y, $z ?? $this->z);
200+
}
201+
return $this;
202+
}
203+
204+
/**
205+
* Returns a new Vector3 taking the maximum of each component in the input vectors.
206+
*/
207+
public static function maxComponents(IntVector3 $vector, IntVector3 ...$vectors) : IntVector3{
208+
$x = $vector->x;
209+
$y = $vector->y;
210+
$z = $vector->z;
211+
foreach($vectors as $position){
212+
$x = max($x, $position->x);
213+
$y = max($y, $position->y);
214+
$z = max($z, $position->z);
215+
}
216+
return new IntVector3($x, $y, $z);
217+
}
218+
219+
/**
220+
* Returns a new Vector3 taking the minimum of each component in the input vectors.
221+
*/
222+
public static function minComponents(IntVector3 $vector, IntVector3 ...$vectors) : IntVector3{
223+
$x = $vector->x;
224+
$y = $vector->y;
225+
$z = $vector->z;
226+
foreach($vectors as $position){
227+
$x = min($x, $position->x);
228+
$y = min($y, $position->y);
229+
$z = min($z, $position->z);
230+
}
231+
return new IntVector3($x, $y, $z);
232+
}
233+
234+
public static function sum(IntVector3 ...$vector3s) : IntVector3{
235+
$x = $y = $z = 0;
236+
foreach($vector3s as $vector3){
237+
$x += $vector3->x;
238+
$y += $vector3->y;
239+
$z += $vector3->z;
240+
}
241+
return new IntVector3($x, $y, $z);
242+
}
243+
}

0 commit comments

Comments
 (0)