Can verify. If you are doing production work with coordinate transforms strongly typing your points to their coord sys and _not_ allowing implicit conversion is a win.
I’ve not used this library (not Rust very much) but the principle is simple to implement and advisable to use whatever typed language you use. So; don’t store northing-easting pairs to vec2. Create a type for it. And call the other value northing, and the other easting. Implement all the algebra you need. I guarantee this will save you from so many headache causing bugs.
keleftheriou · 9h ago
Why not allow implicit conversions from your own defined types?
hansvm · 7h ago
It's the same sort of bug that killed that Mars mission and the same reason some people insist on keyword parameters instead of ordered parameters. People make mistakes, and implicit conversions allow those mistakes to silently propagate. Given how easy it is to strongly type everything and use explicit conversions, the default for most nontrivial software should be closer to TFA rather than allowing implicit conversions or overloading the semantics of a type.
SOLAR_FIELDS · 6h ago
GIS are particularly prone to these sort of human caused accidents. Example is that some GIS take coordinate input as LatLon and some take LonLat.
Another good example is that very often when working with GIS you collate data from multiple sources, as a sibling comment indicates. These sources may be available in all sorts of different coordinate systems and projections and it’s extremely easy to get bad results that are difficult to verify they are bad by these types of bugs.
fc417fc802 · 8h ago
Implicit conversions in general are a very common source of bugs. C(++) implicit widening and narrowing and other such things have bitten me quite a few time. Instead of asking "why not allow" you should instead ask "why allow" and only implement such things when there is a compelling case for it.
fsloth · 9h ago
Because you want to be explicit each time you change coordinate system. You want the code to be so obvious it looks dumb.
lvh · 9h ago
That doesn't really explain why, you're just saying that the thin you claimed was desirable is desirable.
(I don't disagree! I'm just saying: you haven't advanced your argument or answered GP's question.)
tonyarkles · 7h ago
I'll throw a bit more flavour in with the sibling comment talking about transposing x and y.
The system I work on every day has:
- multiple GPS receivers that report latitude, longitude, altitude (MSL) and altitude (HAE)
- an interface to some GeoJSON data where coordinates are stored as longitude, latitude
- a geographically-local Cartesian coordinate frame that is an AEP (Azimuthal Equidistance Projection) with a latitude/longitude origin. The "XYZ" axes of this frame are a NED frame (north, east, down)
- an aircraft-local Cartesian frame with FRD (forward, right, down) axes
- an interface that provides map tiles with zoom/x/y coordinates
- a bunch of other sensors mounted on the aircraft that have their own FRD frames, except the camera which has an RDF (right, down, forward) frame because... reasons.
- terrain RADAR units mounted on the aircraft at specific FRD locations that provide AGL (above ground level) measurements independent of their rotation (the aircraft can be 20 degrees nose-up and we still get a measurement straight down to the ground)
- terrain LIDAR units mounted on the aircraft at specific FRD locations and orientations that provide a straight-line measurement to the ground - if we're over flat ground and the aircraft is 20 degrees nose-up, these report AGL/cos(20 deg)
Keeping track of what frame everything is in is... a daunting task and we've definitely had bugs due to accidentally using a coordinate from the wrong frame. I've been deep into a bunch of this code this week and have been strongly considering doing a zero-cost abstraction similar to what Sguaba is doing, but for C++. I'm pretty sure that we could do it using templates and type tags without really changing any of the underlying math and without implementing a bunch of custom operators but I'm not 100% convinced of that yet.
Another related issue that I don't think is addressed by Sguaba is time. We're hopefully going to get everything standardized to PTP timestamps everywhere but currently all of these sensors are running on unsynchronized clocks and we also have to be careful about keeping track of the origin of a given timestamp and making sure to convert it into the right scale before using it.
bediger4000 · 8h ago
If I may...
Ex structures engineer, current programmer here.
The technique described keeps you, as a programmer, from transposing coordinate variables by type system enforcement. You might have variables x1, y1, x2, y2. If y1 and y2 have a different type than x1 and x2, it's much harder to transpose them. Large flying vehicles often have many coordinate systems. Enforcing types will keep you from using stage 1 variables in a stage 2 context without type conversion.
bediger4000 · 6h ago
I left the aerospace industry in 1992. Before that, I did some work with a program called "BOSOR5" - "Buckling of Shells of Revolution" (https://shellbuckling.com/BOSOR5.php). The X,Y coordinates appears as Y,X in the output. Very confusing, lots of problems because everyone habitually reads X first, then Y, left-to-right.
Imagine how much trouble it was to work on a Saturn 5: https://oikofuge.com/coordinate-axes-apollo-saturn-1/ If you have a type system with different types for all the axes, you will incur far fewer programming-domain errors.
kaibee · 8h ago
Can confirm. Been working on a spaceship colony game still in prototype phase, the code isn't too clean to begin with. Ended up asking the AIs for typed Vector3 in C#, which gave me a starting point.
Oh, no, another Rust vector and matrix library. There's already "glam" and "nalgebra".
Having more than one vector and matrix library is as troublesome for geometry processing as multiple string types are for string processing.
Usual hints for language designers on type basics that become a headache as the language progresses:
- Have a "bool" type, and don't make it equivalent to an integer.
- Have types for vec2 through vec4, and mat2 through mat4. That covers the cases graphics people use constantly. Those are basic, and everyone agrees what they should do.
- Support multidimensional arrays as a standard language feature. Don't get too fancy. Just do it at least as well as FORTRAN does.
- Strings are checked UTF-8.
- Provide some standard error type, or error hierarchy, from which all errors are derived.
Get any of those wrong in the early days of a language and retrofits will become a time sink for users.
Rust got three of those five wrong, and had to be retrofitted to fix them.
isaacimagine · 8h ago
The article is about using nalgebra to create an intuitive library for tranforming between Earth's various coordinate systems. Not "another Rust matrix library".
Animats · 1h ago
OK, it's atop nalgebra. Of course, if you're using glam...
I’ve not used this library (not Rust very much) but the principle is simple to implement and advisable to use whatever typed language you use. So; don’t store northing-easting pairs to vec2. Create a type for it. And call the other value northing, and the other easting. Implement all the algebra you need. I guarantee this will save you from so many headache causing bugs.
Another good example is that very often when working with GIS you collate data from multiple sources, as a sibling comment indicates. These sources may be available in all sorts of different coordinate systems and projections and it’s extremely easy to get bad results that are difficult to verify they are bad by these types of bugs.
(I don't disagree! I'm just saying: you haven't advanced your argument or answered GP's question.)
The system I work on every day has:
- multiple GPS receivers that report latitude, longitude, altitude (MSL) and altitude (HAE)
- an interface to some GeoJSON data where coordinates are stored as longitude, latitude
- a geographically-local Cartesian coordinate frame that is an AEP (Azimuthal Equidistance Projection) with a latitude/longitude origin. The "XYZ" axes of this frame are a NED frame (north, east, down)
- an aircraft-local Cartesian frame with FRD (forward, right, down) axes
- an interface that provides map tiles with zoom/x/y coordinates
- a bunch of other sensors mounted on the aircraft that have their own FRD frames, except the camera which has an RDF (right, down, forward) frame because... reasons.
- terrain RADAR units mounted on the aircraft at specific FRD locations that provide AGL (above ground level) measurements independent of their rotation (the aircraft can be 20 degrees nose-up and we still get a measurement straight down to the ground)
- terrain LIDAR units mounted on the aircraft at specific FRD locations and orientations that provide a straight-line measurement to the ground - if we're over flat ground and the aircraft is 20 degrees nose-up, these report AGL/cos(20 deg)
Keeping track of what frame everything is in is... a daunting task and we've definitely had bugs due to accidentally using a coordinate from the wrong frame. I've been deep into a bunch of this code this week and have been strongly considering doing a zero-cost abstraction similar to what Sguaba is doing, but for C++. I'm pretty sure that we could do it using templates and type tags without really changing any of the underlying math and without implementing a bunch of custom operators but I'm not 100% convinced of that yet.
Another related issue that I don't think is addressed by Sguaba is time. We're hopefully going to get everything standardized to PTP timestamps everywhere but currently all of these sensors are running on unsynchronized clocks and we also have to be careful about keeping track of the origin of a given timestamp and making sure to convert it into the right scale before using it.
Ex structures engineer, current programmer here.
The technique described keeps you, as a programmer, from transposing coordinate variables by type system enforcement. You might have variables x1, y1, x2, y2. If y1 and y2 have a different type than x1 and x2, it's much harder to transpose them. Large flying vehicles often have many coordinate systems. Enforcing types will keep you from using stage 1 variables in a stage 2 context without type conversion.
Imagine how much trouble it was to work on a Saturn 5: https://oikofuge.com/coordinate-axes-apollo-saturn-1/ If you have a type system with different types for all the axes, you will incur far fewer programming-domain errors.
https://gist.github.com/mrkybe/efa70a9ddcba7b5bfe441dafce13e...
It's been a huge time-saver.
Having more than one vector and matrix library is as troublesome for geometry processing as multiple string types are for string processing.
Usual hints for language designers on type basics that become a headache as the language progresses:
- Have a "bool" type, and don't make it equivalent to an integer.
- Have types for vec2 through vec4, and mat2 through mat4. That covers the cases graphics people use constantly. Those are basic, and everyone agrees what they should do.
- Support multidimensional arrays as a standard language feature. Don't get too fancy. Just do it at least as well as FORTRAN does.
- Strings are checked UTF-8.
- Provide some standard error type, or error hierarchy, from which all errors are derived.
Get any of those wrong in the early days of a language and retrofits will become a time sink for users. Rust got three of those five wrong, and had to be retrofitted to fix them.