ianmackenzie / elm-geometry

2D/3D geometry package for Elm
Mozilla Public License 2.0
183 stars 26 forks source link

Add Vector#d.scaleTo functions? #134

Closed ianmackenzie closed 4 years ago

ianmackenzie commented 4 years ago

Allow scaling a vector to a specific length (while leaving zero vectors as is), e.g.

Vector2d.scaleTo : Quantity Float units2 -> Vector2d units1 coordinates -> Vector2d units2 coordinates

This would be equivalent to:

scaleTo givenLength givenVector =
    case Vector2d.direction givenVector of
        Just vectorDirection ->
            Vector2d.withLength givenLength vectorDirection

        Nothing ->
            Vector2d.zero

This operation seems to come up fairly often, but it also seems a bit dangerous to hide inside a helper function since it makes it easy to not consider the zero-vector case.

Swendude commented 4 years ago

I think that just adding the scaleTo definition to the documentation might do the job! This leaves the user free to change the handling of Nothing to their specific use case!

ianmackenzie commented 4 years ago

It occurs to me that Vector#d.scaleTo could actually replace Vector#d.normalize in some future breaking release - if you really wanted the current behavior of normalize you could replace it with scaleTo (Quantity.float 1).

g-belmonte commented 4 years ago

What would be the implication of allowing a zero direction? Having a zero direction would make the Maybe disappear, and then we would have

scaleTo givenLength givenVector =
    Vector2d.withLength givenLength (Vector#d.direction givenVector)

and

normalize =
    scaleTo (Quantity.float 1)

--- EDIT --- I figured out that I was mixing concepts. :sweat_smile: The direction is always a unitary vector. But in that case, maybe it's better leaving to the user the extraction of the direction from the vector and then dealing with scaling or having a zero vector.

ianmackenzie commented 4 years ago

I mean that's exactly how things are now - "extraction of the direction from the vector" is Vector#d.direction, and then "dealing with scaling or having a zero vector" is some combination of Maybe.withDefault and Vector#d.withLength (or an explicit case expression as shown above). But the use case of "take one vector and scale it to a given length" seems to come up often enough in practice (it's come up both in discussions with others and in my own code) that it seemed useful to have a helper function for it.

g-belmonte commented 4 years ago

Maybe if we leave a warning at the docs, saying that scaling a zero vector is equal to a zero vector? Then I think it would be good to go :)

g-belmonte commented 4 years ago

I mean, this seems to be the most common case, so if people want a different behavior, they could easily implement it with a variation of the code snippet that you left on the first comment

ianmackenzie commented 4 years ago

Yeah, I think that it would be fine if scaling a zero vector gave a zero vector - it makes sense, in most cases I can think of that's what you would want anyways, and unlike having a 'zero direction' it doesn't break type safety (since zero vectors are definitely a valid thing).

ianmackenzie commented 4 years ago

Implemented in #137, thanks @g-belmonte!