
[ad_1]
Let’s first outline a brand new quantity. No worries, it is a simple one.
Or, to place it merely: f = √3 × i, with i being the imaginary unit. With this, a rotation by 60 levels clockwise is similar as multiplication by 1/2 × (1 – f), and rotation by 60 levels counter-clockwise the identical as multiplication by 1/2 × (1 + f). If this sounds unusual, do not forget that multiplication by a fancy quantity is similar as rotation within the 2D aircraft. We simply “squash” the complicated numbers within the imaginary course a bit (by √3) to not should take care of sq. roots … or non-integers, for that matter.
We can even write the purpose (a,b) as a + b × f.
This lets us rotate any level within the aircraft; for instance, the purpose (2,0) = 2 + 0 × f rotates to (1,-1), then to (-1,-1), (-2,0), (-1,1), (1,1) and at last again to (2,0), just by multiplying it.
Of course, we want a approach to translate these factors from our coordinates to these we do the rotations in, after which again once more. For this, one other bit of data is required: If the purpose we do the rotation round is to the “left” or to the “proper” of the vertical line. For simplicity, we declare that’s has a “wobble” worth w of 0 if it is to the left of it (like the middle of the rotation [0,0] in your backside two photos), and of 1 if it is to the fitting of it. This extends our unique factors to be three-dimensional; (x, y, w), with “w” being both 0 or 1 after normalisation. The normalisation perform is:
NORM: (x, y, w) -> (x + flooring(w / 2), y, w mod 2), with the “mod” operation outlined such that it solely returns optimistic values or zero.
Our algorithm now appears as follows:
-
Transform our factors (a, b, c) to their positions relative to the rotational centre (x, y, w) by calculating (a – x, b – y, c – w), then normalising the consequence. This places the rotational centre at (0,0,0) clearly.
-
Transform our factors from their “native” coordinates to the rotational complicated ones: (a, b, c) -> (2 × a + c, b) = 2 × a + c + b × f
-
Rotate our factors by multiplying them with one of many rotational numbers above, as wanted.
-
Ra-transform the factors again from the rotational coordinates to their “native” ones: (r, s) -> (flooring(r / 2), s, r mod 2), with “mod” outlined as above.
-
Re-transform the factors again to their unique place by including them to the rotational centre (x, y, z) and normalising.
A easy model of our “triplex” numbers based mostly f in C++ would appear like this:
class hex {
public:
int x;
int y;
int w; /* "wobble"; for any given map, y+w is both odd or
even for ALL hexes of that map */
hex(int x, int y, int w) : x(x), y(y), w(w) {}
/* remainder of the implementation */
};
class triplex {
public:
int r; /* actual half */
int s; /* f-imaginary half */
triplex(int new_r, int new_s) : r(new_r), s(new_s) {}
triplex(const hex &hexfield)
{
r = hexfield.x * 2 + hexfield.w;
s = hexfield.y;
}
triplex(const triplex &different)
{
this->r = different.r; this->s = different.s;
}
non-public:
/* C++ has loopy integer division and mod semantics. */
int _div(int a, unsigned int b)
{
int res = a / b;
if( a < 0 && a % b != 0 ) { res -= 1; }
return res;
}
int _mod(int a, unsigned int b)
{
int res = a % b;
if( res < 0 ) { res += a; }
return res;
}
public:
/*
* Self-assignment operator; easy sufficient
*/
triplex & operator=(const triplex &rhs)
{
this->r = rhs.r; this->s = rhs.s;
return *this;
}
/*
* Multiplication operators - our fundamental workhorse
* Watch out for overflows
*/
triplex & operator*=(const triplex &rhs)
{
/*
* (this->r + this->s * f) * (rhs.r + rhs.s * f)
* = this->r * rhs.r + (this->r * rhs.s + this->s * rhs.r ) * f
* + this->s * rhs.s * f * f
*
* ... remembering that f * f = -3 ...
*
* = (this->r * rhs.r - 3 * this->s * rhs.s)
* + (this->r * rhs.s + this->s * rhs.r) * f
*/
int new_r = this->r * rhs.r - 3 * this->s * rhs.s;
int new_s = this->r * rhs.s + this->s * rhs.r;
this->r = new_r; this->s = new_s;
return *this;
}
const triplex operator*(const triplex &different)
{
return triplex(*this) *= different;
}
/*
* Now for the rotations ...
*/
triplex rotate60CW() /* rotate this by 60 levels clockwise */
{
/*
* The rotation is similar as multiplikation with (1,-1)
* adopted by halving all values (multiplication by (1/2, 0).
* If the values come from transformation from a hex subject,
* they are going to at all times land again on the hex subject; else
* we'd lose some data as a result of final step.
*/
(*this) *= triplex(1, -1);
this->r /= 2;
this->s /= 2;
}
triplex rotate60CCW() /* Same, counter-clockwise */
{
(*this) *= triplex(1, 1);
this->r /= 2;
this->s /= 2;
}
/*
* Finally, we might prefer to get a hex again (truly, I'd
* usually create this as a constructor of the hex class)
*/
operator hex()
{
return hex(_div(this->r, 2), this->s, _mod(this->r, 2));
}
};
[ad_2]