-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hex division is unstable #9
Comments
Thank you for noticing this !
I think any integer-based primitive will have the same rounding issue. Therefore I only see the following solutions:
What do you think ? |
There might actually be a third option where you only divide the two largest axis or the two axis with the largest remainder (I'm not completely sure which one will work best). This will probably still give issues with deciding exactly where exactly to place the new hex, but it at least prevents skipping too many hexes (e.g. Otherwise adding documentation on this issue will help a lot with any possible confusion. |
Again, there are only 2 axis, the third one is just a computed value. I think the solution to your problem and not skip tiles is to use floating points, either:
Or, to use a |
Using I understand that the It's easy to create a temporary variable for z, take for example this modified round function from https://www.redblobgames.com/grids/hexagons/implementation.html#rounding
It still respects the fact we use axial coordinates, but also uses z for the logic. |
The For the rounding, fn rounded_div(self, rhs: Self) -> Self {
let [mut xf, mut yf] = [self.x as f32, self.y as f32];
xf /= rhs.x as f32;
yf /= rhs.y as f32;
Hex::round((xf, yf))
} Should avoid the classic rounding issue and not skip any EDIT: |
Looks good to me. Apologies for not being clearer about what I meant with the All that would be left is to decide on which of these methods should be the default. |
@nuggetInc I opened a merge request adressing this. At this point I'm not sure which division should be the default. Does it make sense to force floating point division on everything by default ? and on the other hand, does it make sense to have classic integer division? |
Not completely sure what's the best place to comment on this is now, feel free to direct me. I personally think it makes most sense to use floating point division even for For the case that someone does need the "classic" rounding a |
If you divide with rounding you have no guarantee that the new length will be equal to the old length divided, I tested this in #21 (check the tests) and did not have the expected result |
It seems you're right. certain hex positions such as If we consider the length as the "correct" value, then we might as well use it for the division. fn divide(self, rhs: i32) -> Self {
let new_length = self.length() / rhs;
let s = new_length as f32 / self.length() as f32;
Self::ZERO.lerp(self, s)
} The way it works is we first divide the length (lets say 3) to find the new expected length (dividing by 2 so 1). Then we figure out how far along the new length is along the old (in this case 1/3). And at last we use lerp to find a hex at that point. All previous problems with rounding seem to have been fixed with this solution. Should we switch to this? |
@nuggetInc @alice-i-cecile Could you both review #28 and confirm that the PR correctly adresses the division issue ? Also, I didn't update After that I will release the 0.3.0 |
> Closes #9 > Addresses #27 # Work done - [x] `Hex::length` and `Hex::ulength` rework to reduce overflowing cases (#27) - [ ] Reworked `Div` impls for `Hex` to respect expected `length` expectations (#9) - [x] `Div<f32>` - [x] `Div<i32>` - [ ] `Div<Self>` - [x] Adapted `Rem` impls to match the new division - [x] Added `Hex::abs` method - [x] Updated example to showcase the division and rotations
There are two major problems with the current
Hex
division implementations:Not considering the third axis gives unstable results (e.g.
Hex(2, -1, -1) / 2 == Hex(1, 0, -1)
whileHex(1, 1, -2) / 2 == Hex(0, 0, 0)
).Often when dividing hexes the resulting hex is in a location that doesn’t fully make sense (e.g.
Hex(1, -1, 0) / Hex(-1, 1, 0) == Hex(-1, -1, 2)
which is further from the center than the initial two).One possible solution for dividing by integers would be to use floating point numbers and round those, but this might result in similar issues due to rounding errors.
It might have to be considered removing hex division altogether until a solid solution is found.
This is a first issue, feedback is appreciated.
The text was updated successfully, but these errors were encountered: