Re: [eigen] Transform products

[ Thread Index | Date Index | More Archives ]

ok, some news of my progress,
so after trying to implement an as clever as possible Transform
product, I gave up, I finally added an Homogeneous expression and
hnormalized() function. Currently the Homogeneous class is not
efficient, but the goal is to overload its operator* with a MatrixBase
and bypass Homogeneous::coeff(). Then, in some very specific cases,
Transform will automatically use this Homogeneous expression to
implement its operator* with MatrixBase.
So to explain the planed logic, let's assume we are working in 3D, A
and P be an affine and projective transformation, m stands for matrix,
v for vector, and ? for any size:

A * v3  =>  v3   // implicit call to v3.homogeneous()
A * m33 => A  // m33 is interpreted as a linear transform
A * m34 => A  // m34 is interpreted as an affine transform
A * m44 => P  // m44 is interpreted as a projective transform
A * m3? => not allowed (because it is confusing with A * m33/34)
A * m3?.colwise().homogeneous() => m3?
A * m4? => not allowed

m33 * A => A
m34 * A => A
m44 * A => P

P * v3  =>  v4
P * v4  =>  v4
P * m33 => P
P * m34 => P
P * m44 => P
P * m3? => not allowed
P * m3?.colwise().homogeneous() => m4?
P * m4? => m4?  // only if ?==Dynamic such that
                             it is clear that it represents a set of v4

m33 * P => P
m34 * P => P
m44 * P => P

is it reasonable to you? are there any other cases that should be handled?

Actually, thanks to the optimized "return-by-value" trick of the other
thread, I managed to handle things like:

v3 = P * v3;    // auto homogeneous normalization
v3 = P * v4;    // auto homogeneous normalization
v4 = P * v3;
v3 = (P * v3) * 2; // does not compile because P * v3 defaults to a v4

however I'm not 100% sure that's really worth it.

Regarding the 3 different version of Transform (Affine,AffineCompact,
and Projective) I currently added a third template parameter. The
advantage is that Transform<scalar,dim> will still give the same kind
of transformation than it currently does. However, I'm tempted to go
for 3 different classes inheriting the same base class (API-wise I
think it is cleaner), but then we could not keep the name Transform to
represent a "square affine" transformation anymore (well we can have
both Affine and Transform to temporarily keep the compatibility).


On Sun, Feb 22, 2009 at 4:20 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:
> I have to say that i haven't been thinking about that intensely, and
> that contrary to you and Keir, these days I am not even a user of the
> Transform class (I don't contribute anymore to any user project) so i
> just have general uninformed opinions.
> 2009/2/21 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:
> > I have to say: I'm puzzled!
> >
> > at least I agree to add homogeneous normalization functions:
> >  v.hnormalized();
> >  data.colwise().hnormalized();
> >  data.rowwise().hnormalized();
> > (for the name feel free to suggest something different)
> The name sounds good to me (I don't remember suggesting that but that
> sounds like a good idea!)
> > and then a "projective transform" * "set of non homogeneous vectors"
> > would not perform an automatic normalization, but return homogeneous
> > vectors. Then it is up to the user to normalize the result.
> Can we make sure we mean the same thing by "homogeneous vectors " and
> "non homogeneous vectors" ?
> homogeneous : size d+1
> non homogeneous: size d
> Then yes, I agree with your suggestion. projective *
> any_vec_homogeneous_or_not returns homogeneous.
> Indeed, normalizing the result is not always possible, only the user
> can know if it's possible, so leave that up to him.
> > I'm not fan of the "as homogeneous" expression because it would
> > require a if inside coeff,
> Good point.
> > but since it might be removed by the
> > compiler, why not...
> Indeed there's a risk it will not always be, depending on storage
> order, in batch operations on a dynamic number of vectors...
> >  I think that's better to make Transform good
> > enough so that such an expression would not be needed. And by the way,
> > currently you can do:
> > VectorType v;
> > HVectorType hv;
> > // ... work with v
> > // then you temporally need an homogeneous vector:
> > hv << v, 1;
> > // use hv
> This solution has the other problem that a useless copy of v is performed..
> I think, the best solution then might be to make asHomogeneous()
> return a proxy, not an expression. It would be used just to resolve
> overloading of operator*. I.e. we'd have a Transform*HomogeneousProxy
> that would take the vector inside the proxy and continue with a "1"
> for the last component.
> > About splitting the current Transform into 3 versions... well that
> > would probably be ideal, but this would significantly increase the
> > number of product combinations... I still have to think about it.
> It could end up in more lines of code but that code would also be
> simpler, each class having its own separate meaning, and requiring
> less template logic.
> But if you prefer you might save some LOC's by making it just a single
> class Transform with a template parameter (which then should default
> to "affine transform stored as big matrix" for optimal compatibility).
> Cheers,
> Benoit

Mail converted by MHonArc 2.6.19+