You're exactly right - if you construct a function like the following, I 
think it will almost certainly result in four separate transformations 
every time it's called:

compositeTransformation1 : Point3d -> Point3d
compositeTransformation1 =
    Point3d.scaleAbout Point3d.origin 5 >> Point3d.rotateAround Axis3d.z 
(degrees 
90) >> Point3d.translateBy (Vector3d ( 1, 2, 3 )) >> Point3d.mirrorAcross 
Plane3d.xy

In many cases that's fine (if you're only doing it for a handful of points, 
for instance), but if you need a more efficient version you can do it using 
frames:

transformedFrame : Frame3d
transformedFrame =
    Frame3d.xyz |> Frame3d.rotateAround Axis3d.z (degrees 90) |> 
Frame3d.translateBy 
(Vector3d ( 1, 2, 3 ) |> Frame3d.mirrorAcross Plane3d.xy

compositeTransformation2 : Point3d -> Point3d
compositeTransformation2 =
    Point3d.scaleAbout Point3d.origin 5 >> Point3d.placeIn transformedFrame

You still need to apply the scaleAbout separately since you can't scale a 
Frame3d, but at least scaling is a relatively cheap operation.

In general, yes, using matrices would likely be a bit more efficient, but 
you can get pretty close using techniques like the above, and I think the 
expressiveness/clarity/flexibility is better. Precision should also be 
improved - even disregarding the fact that the linear-algebra package uses 
single-precision floats internally (via Float32Array), specialized 
transformation functions like scaleAbout can do things like subtract the 
given center point, then scale, then re-add the given center point. This 
has better numerical stability than the equivalent transformation matrix, 
which will effectively scale everything about the origin and then apply a 
(potentially large) translation to drag everything back to where it should 
be. (Several of these tradeoffs are probably affected by my own goals - I 
want opensolid/geometry to be a great general-purpose geometry library, but 
I'm personally more focused on stuff like computer-aided design apps where 
precision is critical than things like games that have much more strict 
performance requirements.)

By the way, the interop package I mentioned earlier has now been published: 
http://package.elm-lang.org/packages/opensolid/linear-algebra/latest.

On Monday, 8 May 2017 05:22:05 UTC-4, Rupert Smith wrote:
>
> On Sunday, May 7, 2017 at 10:02:43 PM UTC+1, Rupert Smith wrote:
>>
>> On Friday, May 5, 2017 at 7:55:22 PM UTC+1, Ian Mackenzie wrote:
>>>
>>> So, nice library with lots of features, missed chance to work with a 
>>>> better abstraction.
>>>>
>>>
>>> Ouch =) I've done lots of work with matrix-based libraries, and I've 
>>> personally found matrices (and related stuff like quaternions) very 
>>> powerful and flexible but also confusion- and error-prone. The OpenSolid 
>>> libraries are my attempt to provide a better, more geometrically meaningful 
>>> abstraction that still allows you to get good performance.
>>>
>>
>> Sorry, my bad and thanks for the explanation. I guess I was a little 
>> fixated on the matrix approach, but with your explanation it is clear that 
>> your approach is at least as good.
>>
>
> There is potentially an advantage with matrices versus functions. A matrix 
> could be thought of as a function, in the sense that its values capture a 
> particular function that can be applied by multiplying by it. So you have 
> captured the function as a lambda. Lambdas are opaque though, and when 
> chained together to produce a new function, there is no way to guarantee 
> that they will combine in such a way that they reduce to the simplest or 
> most efficient representation; the compiler may do a good job though.
>
> Suppose you have a complex chain of transformations like: scale, rotate, 
> translate (requires 3x3 matrix for 2d work), mirror. Represent this with 
> matrices M1, .., M4. The entire transformation can then be captured as a 
> single matrix Mt = M1 . M2 . M3 . M4. As lambdas, my assumption is the 
> compiler will not be smart enough to reduce it so neatly, and it will 
> always be applied as 4 separate operations.
>
> I guess you already know this... :-)
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to