Skip to content
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

Provide point types with coordinate system type-safety #32017

Merged
merged 14 commits into from
Jul 7, 2020

Conversation

jbytheway
Copy link
Contributor

@jbytheway jbytheway commented Jun 30, 2019

Summary

SUMMARY: Infrastructure "Provide point types with coordinate system type safety"

Purpose of change

Cataclysm has a lot of different coordinate systems. It's confusing to work with them, but even more so it's confusing to read code working with points and have no idea what type system they're in.

This PR aims to provide a collection of point/tripoint types which encode the coordinate system in their type, so that it becomes clear what points mean and easier to correctly use APIs that have point/tripoint arguments or return values.

Describe the solution

  • New namespace coords to contain all the details.
  • Enums therein to define all the possible scales and origins for which we need coordinate systems.
  • A class template wrapping a point or tripoint, with added coordinate system info.
  • Functions project_to and project_remain for coordinate system transformations. Between them, these two functions can do anything that any of the functions in coordinate_conversions.h can do.
  • Typedefs for the common point/tripoint and coordinate system combinations for ease of use.
  • Suitable operator overloads.
  • constexpr all the things.
  • Add Catch::Generator and Catch::StringMaker specializations for easier working with point/tripoint in tests.
  • Write tests for all the above.

Deferred to a future PR:

  • Support for vehicle space coordinates.
  • Support for map space coordinates.

Note that this initial PR does not intend to actually convert code to use the new types, although I will try to do at least some experiments with them to verify that things work smoothly.

For the purposes of this PR, look at the tests for usage examples. For broader context, see #41693 which demonstrates the use of these types on a fairly large scale for various overmap-related stuff.

Describe alternatives you've considered

There are other ways to express the coordinate systems than the scale/origin pair I've chosen. This approach is very nice for the conversion functions. I think it will owrk nicely in general, but that requires further experimentation.

Additional context

The new class template is mostly agnostic to the underlying implementation of the point type, so there is room to support more storage choices in the same framework, e.g. if we wanted to have a more compact type that used less memory and offered less precision.

namespace coords
{

enum class scale {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a tag type (not enumeration value) is better. It allows easier adding of new systems. All properties (like scaling/absolute vs relative) can be done withing that tag type.

E.g.

class sub_map_system;

class map_system {
// this would allow converting map_system to sub_map_system, but not to say vehicle coordinates
// instead of a debug message this would yield a compiler error (as there is no factor_to( vehicle_system) function)
    static int factor_to( const sub_map_system & ) {
        return 12;
    }
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the code is simpler with two independent features rather than a tag type that controls all aspects. Could use types rather than an enum. I chose the enum because more meta-programming logic can be written in "regular C++" constexpr functions, rather than type-specialization style, which I was hoping would be clearer and easier to follow.

I'll try to keep both approaches in mind, though, if this version gets unwieldy.

@ZhilkinSerg ZhilkinSerg added [C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style labels Jul 1, 2019
@jbytheway jbytheway force-pushed the point_type_safety branch 3 times, most recently from 6e07ea5 to 80f77cb Compare July 2, 2019 22:02
jbytheway added a commit to jbytheway/Cataclysm-DDA that referenced this pull request Jul 10, 2019
Remove almost all (x, y, z) APIs and replace wityh point / tripoint
APIs.

This is a first step towards making these APIs type-safe (CleverRaven#32017).

A couple of APIs remain because they're more complex to change and this
commit was already very big.
ZhilkinSerg pushed a commit that referenced this pull request Jul 11, 2019
* Typo

* Add some point / tripoint overloads for APIs

A bunch of map / overmap functions take x, y, z coordinates.  Add
overloads to (some of) those taking a point or tripoint.

For now, those overloads just forward to the original function, but the
ultimate goal is to remove the originals and only have the new
overloads.

* Overhaul overmapbuffer APIs

Remove almost all (x, y, z) APIs and replace wityh point / tripoint
APIs.

This is a first step towards making these APIs type-safe (#32017).

A couple of APIs remain because they're more complex to change and this
commit was already very big.
KorGgenT pushed a commit to b0urgeoisie/Cataclysm-DDA that referenced this pull request Jul 14, 2019
* Typo

* Add some point / tripoint overloads for APIs

A bunch of map / overmap functions take x, y, z coordinates.  Add
overloads to (some of) those taking a point or tripoint.

For now, those overloads just forward to the original function, but the
ultimate goal is to remove the originals and only have the new
overloads.

* Overhaul overmapbuffer APIs

Remove almost all (x, y, z) APIs and replace wityh point / tripoint
APIs.

This is a first step towards making these APIs type-safe (CleverRaven#32017).

A couple of APIs remain because they're more complex to change and this
commit was already very big.
@stale
Copy link

stale bot commented Aug 1, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Closed for lack of activity, but still valid. label Aug 1, 2019
@jbytheway
Copy link
Contributor Author

Thanks, stalebot. Still working on it :).

overmap_terrain,
segment,
overmap,
vehicle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vehicle scale should possibly be split into two scales: vehicle_mount (the unrotated nominal displacement from the 0,0,0 position) and vehicle_actual (the current projection of a vehicle_mount along a tileray). Perhaps those should be special origins.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I haven't delved too deeply into vehicle stuff yet. My thoughts were that the mount coords would be origin vehicle, scale vehicle, while the projected-into-world coordinates would be origin vehicle, scale map_square. But I'm not too tied to that idea yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too particular about how they're laid out, I just hate:
void coord_translate( int dir, const point &pivot, const point &p, point &q ) because it's not immediately clear that p and q are actually supposed to be separate types and whether pivot is the same or a different type.

If that becomes
void coord_translate( int dir, const veh_veh_point &pivot, const veh_veh_point &p, veh_ms_point &q ) then I'm satisfied, aside from veh_veh_point looking kind of silly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scale veh should be scale mnt, so:
void coord_translate( int dir, const veh_mnt_point &pivot, const veh_mnt_point &p, veh_ms_point &q )
which doesn't look too bad.

@jbytheway jbytheway force-pushed the point_type_safety branch from 70fce43 to 22bf0b5 Compare July 1, 2020 01:50
@jbytheway jbytheway changed the title [WIP][CR] Provide point types with coordinate system type-safety Provide point types with coordinate system type-safety Jul 1, 2020
@jbytheway
Copy link
Contributor Author

Now that #41693 demonstrates the end-goal of this effort a little more clearly I think this PR is in a state where it can be reasonably reviewed, and I'm marking it ready.

The code here still doesn't actually do anything, but adding enough to allow it to will make for a huge PR (like #41693) so I'm offering this as the first bite-sized chunk. More will follow once this is merged.

@jbytheway jbytheway marked this pull request as ready for review July 1, 2020 01:53
@jbytheway
Copy link
Contributor Author

Hah, I've just realised that it's exactly one year from opening this PR that I mark it ready for review. Interesting coincidence...

@jbytheway
Copy link
Contributor Author

Hopefully now fixed the clang-tidy issues. The test failures looked unrelated.

@jbytheway
Copy link
Contributor Author

CI now looks good to me (as good as it can be, right now, anyway).

jbytheway added 14 commits July 7, 2020 09:46
This takes the form of a wrapper class around point and/or tripoint
which adds type parameters for the coordinate system in which the point
has meaning.

Added some helper functions to point.h needed to implement the
conversions.
This tests project_to and project_remain.
Add arithmetic and comparison operator overloads, constructors, hashing.
We need a complicated way to report constepxr errors in older gcc
versions because gcc 5.3 didn't quite implement all of C++14 constexpr
properly.

Add a macro that performs the workaround solution on gcc < 6, but uses a
neater solution (including an error message) on other compilers.
After reading this code more, I've decided that the notation and
mnemonics I'm adding are easier to understand if you put the origin
before scale.

e.g. point_sm_ms is a "submap map square", and point_rel_omt is a
"relative overmap terrain".
Using these points in a larger proof of concept revealed the need for
more operators.  Add them.

* Allow adding or subtracting raw points from coord_points (so that e.g.
  point_north, etc. can be used easily).
* Allow more mixed-dimension arithmetic.
* Allow subtracting two similarly-typed points to create a relative
  point.
* Allow non-const access to individual coordinates.
They call a virtual function from the constructor.  Marking them final
suppresses the clang warning about this.
We are specifically testing the APIs that this check would refactor the
code away from.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style (P5 - Long-term) Long-term WIP, may stay on the list for a while.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants