-
Notifications
You must be signed in to change notification settings - Fork 26
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
Add dedicated transformation types/modules? #79
Comments
Could get fancy and have phantom type parameters to tag transformations as non-scaling or non-shearing, to support transforming directions or circles etc. Perhaps: module Transformation2d
identity : Transformation units coordinates a
translateBy :
Vector2d units coordinates
-> Transformation2d units coordinates a
rotateAround :
Point2d units coordinates
-> Angle
-> Transformation2d units coordinates a
scaleAbout :
Point2d units coordinates
-> Float
-> Transformation2d units coordinates { a | scaling : Allowed }
scaleAlong :
Axis2d units coordinates
-> Float
-> Transformation2d units coordinates { a | scaling : Allowed, shear : Allowed }
sequence :
List (Transformation2d units coordinates a)
-> Transformation2d units coordinates a module Triangle2d
apply :
Transformation2d units coordinates { scaling : Allowed, shear : Allowed }
-> Triangle2d units coordinates
-> Triangle2d units coordinates module Circle2d
apply :
Transformation2d units coordinates { scaling : Allowed }
-> Circle2d units coordinates
-> Circle2d units coordinates module Frame2d
apply :
Transformation2d units coordinates {}
-> Frame2d units coordinates
-> Frame2d units coordinates |
Perhaps have the function called let
transformation =
Rotation.around axis angle
in
List.map (Point3d.apply transformation) points Less likely to be interpreted as the 'default' function to use for transformations...and a bit shorter! |
First of all, great package! I have started experimenting with Elm by writing an astrodynamics package. In this field you often want to apply the same transformation to the position and velocity vectors. Thus, being able to reuse a transformation would make the code simpler and improve efficiency at the same time, e.g. https://github.com/helgee/elm-astrodynamics/blob/master/src/Astrodynamics.elm#L216 So, this is my 👍 |
Thanks @helgee! I think there are lots of useful applications of a generic cartesian : KeplerianElements -> Float -> ( Vector3d, Vector3d )
cartesian elements mu =
let
semiLatus =
if almostEqual elements.eccentricity 0 then
elements.semiMajorAxis
else
elements.semiMajorAxis * (1 - elements.eccentricity ^ 2)
( rPerifocal, vPerifocal ) =
perifocal semiLatus elements.eccentricity elements.trueAnomaly mu
rotatedFrame =
Frame3d.atOrigin
|> Frame3d.rotateAround Axis3d.z elements.argumentOfPericenter
|> Frame3d.rotateAround Axis3d.x elements.inclination
|> Frame3d.rotateAround Axis3d.z elements.ascendingNode
in
( rPerifocal |> Vector3d.placeIn rotatedFrame
, vPerifocal |> Vector3d.placeIn rotatedFrame
) where you construct a rotated frame and then "place" the vectors "in" that frame. This is equivalent to treating I can imagine Really excited to see you working on an astrodynamics package for Elm - looking forward to seeing what you come up with! |
Just wondering if a more transformation oriented API would make sense? Since the reason for using these is to compose transformations (otherwise you might as well use the functions in the specific modules). So more like: module Transformation2d
identity : Transformation units coordinates
translateBy :
Vector2d units coordinates
-> Transformation2d units coordinates
-> Transformation2d units coordinates
rotate:
Angle
-> Transformation2d units coordinates
-> Transformation2d units coordinates
scale :
Float
-> Transformation2d units coordinates
-> Transformation2d units coordinates
scaleXY :
Float
-> Float
-> Transformation2d units coordinates
-> Transformation2d units coordinates
-- any maybe low level
mult : ((Float, Float, Float), (Float, Float, Float)) -> Transformation2d units coordinates -> Transformation2d units coordinates
|
That could make sense - that would get around the issue of arguments to I actually can see use cases for I also kind of like the simplicity and orthogonality of the current API: |
Perhaps, but they compose quite nicely. myTransformation : Transformation2d units coordinates -> Transformation2d units coordinates
myTransformation =
Transformation2d.scale 2
>> Transformation2d.translateBy (Vector2d.fromComponents 200 -400)
>> Transformation2d.rotate (Angle.degrees 40)
>> Transformation2d.translateBy (Vector2d.fromComponents 100 200) vs myTransformation : Transformation2d units coordinates -> Transformation2d units coordinates
myTransformation initial =
Transformation2d.sequence
[ initial
, Transformation2d.scale 2
, Transformation2d.translateBy (Vector2d.fromComponents 200 -400)
, Transformation2d.rotate (Angle.degrees 40)
, Transformation2d.translateBy (Vector2d.fromComponents 100 200)
] Anyway, I think both would be pretty nice, so no strong argument here. |
True - that is cool! Although I would probably write your second example as myTransformation : Transformation2d units coordinates
myTransformation =
Transformation2d.sequence
[ Transformation2d.scale 2
, Transformation2d.translateBy (Vector2d.fromComponents 200 -400)
, Transformation2d.rotate (Angle.degrees 40)
, Transformation2d.translateBy (Vector2d.fromComponents 100 200)
] which you could then compose by including it in other sequences: finalTransformation : Transformation2d units coordinates
finalTransformation =
Transformation2d.sequence
[ Transformation2d.mirrorAcross Axis2d.x
, myTransformation
, Transformation2d.mirrorAcross Axis2d.y
] |
For efficient composite transformations:
then have
Point3d.transformBy : Transformation3d -> Point3d -> Point3d
etc.I don't love having two ways to do the same thing (if you want to rotate a bunch of points, do you use
Point3d.rotateAround
orPoint3d.transformBy
withTransformation3d.rotateAround
?) but this may be the cleanest solution that allows for efficient, non-error-prone transformations.Should scaling be supported? Then you couldn't transform frames, directions etc...unless
Transformation3d
had a type variable that indicated whether it wasRigid
orNonRigid
.Could get fancier and allow conversions between units/coordinate systems...perhaps
Transformation3d
would have type variablesrigidity
,inputCoordinates
andoutputCoordinates
and include functionsrelativeTo
,placeIn
andconvertUnits
or similar? (This is assuming #66 happens.) This would, however, mean that you could only usesequence
for a sequence of transformations that did not change units or coordinates - those would need a slightly different approach.The text was updated successfully, but these errors were encountered: