views:

113

answers:

3

I'm writing a computer graphics application that makes use of several different libraries that provide many of the required features.

For example, in college I wrote quaternion, optimized 3 vector, and optimized 4x4 matrix classes that I like to use since they are efficient and I'm very familiar with them. I also wrote a K-D Tree implementation that only depends on the STL.

Finally, I'm using ITK to compute the minimum eigenvalue (and associated eigenvector) of a given symmetric real matrix, among other things.

With all of these libraries containing their own matrix and vector implementations, I find myself doing a lot of this sort of thing:

FixedPointType closestPointCoords;
KdTree::HyperPoint target(3);
target[0] = transformedPoint[0];
target[1] = transformedPoint[1];
target[2] = transformedPoint[2];
KdTree::Neighbor result = FixedPointTree.FindNearestNeighbor(target);
minimumDistance = result.GetDistance();
closestPointCoords[0] = result.GetPoint().Get(0);
closestPointCoords[1] = result.GetPoint().Get(1);
closestPointCoords[2] = result.GetPoint().Get(2);

Obviously I could write a function that looks something like:

FixedPointType ConvertHyperPointToFixedPointType(const KdTree::HyperPoint &p)
{
    FixedPointType fixedPoint;
    fixedPoint[0] = p[0];
    fixedPoint[1] = p[1];
    fixedPoint[2] = p[2];

    return fixedPoint;
 }

I'd like to avoid adding inter-library dependancy by doing something like this:

class HyperPoint
{
    ...
    operator FixedPointType() 
    {
         // Same content as ConvertHyperPointToFixedPointType above
    }
    ...
};

But I'm wondering if anyone has come up with a more elegant solution to this problem.

Perhaps I should take a page out of the .NET book and create a static Convert class?

How have you handled type redundancy across libraries and the need to frequently convert between the various types?

Is the Adapter pattern appropriate here?

UPDATE
After some more exploring I came across TypeConverter. So this problem looks like it's been addressed in C#. I'm still looking for a clean, efficient and simple way to do it in C++. So far I'm thinking the canonical types, or maybe just the bare ConvertHyperPointToFixedPointType kind of functions.

UPDATE 2 After even more reading it sounds like the canonical type will actually act as the shim. See this paper for more info.

Here's some sample code to illustrate my current inclination:

class VectorConverter
{
public:
    VectorConverter(const VectorImp1 &v1)
    {
        _data[0] = v1[0];
        _data[1] = v1[1];
        _data[2] = v1[2];
    }

    VectorConverter(const VectorImp2 &v2)
    {
        _data[0] = v2.Get(0);
        _data[1] = v2.Get(1);
        _data[2] = v2.Get(2);
    }

    operator VectorImp1()
    {
        return VectorImp1(_data[0], _data[1], _data[2]);
    }

    operator VectorImp2()
    {
        VectorImp2 v2;
        v2.Set(0, _data[0]);
        v2.Set(1, _data[1]);
        v2.Set(2, _data[2]);
        return v2;
    }

    // actual vector implementation goes here or a wrapper around an existing one
};

// example usage
VectorImp1 closestPointCoords, target;
// for the sake of illustration I included the cast, but you could implicitly cast
KdTree::Neighbor result = FixedPointTree.FindNearestNeighbor((VectorImp2)VectorConverter(target));
minimumDistance = result.GetDistance();
closestPointCoords = (VectorImp1)VectorConverter(result.GetPoint());

Thanks for all your help. Feel free to update this post if someone comes across something better.

+1  A: 

CAVEAT: I don't have a compiler in front of me right now, and I'm suddenly unsure about the SFINAE part (not sure whether it applies to the function body, or only to the parameter types). Somebody please correct this if it's wrong.

In C++, you could take advantage of the similar syntax of the different classes to create a single function template:

template <class ToType, class FromType>
ToType ConvertPoint(const FromType& FromValue)
{
  ToType ToValue;
  ToValue[0] = FromValue[0];
  ToValue[1] = FromValue[1];
  ToValue[2] = FromValue[2];

  return ToValue;
}

// If the version above failed, the compiler will try this one.
// This is called SFINAE
template <class ToType, class FromType>
ToType ConvertPoint(const FromType& FromValue)
{
  ToType ToValue;
  ToValue[0] = FromValue.Get(0);
  ToValue[1] = FromValue.Get(1);
  ToValue[2] = FromValue.Get(2);

  return ToValue;
}

// Usage:
KdTree::HyperPoint hyperPoint;
FixedPointType fixedPoint = ConvertPoint<FixedPointType>(hyperPoint);

I guess you can do the same in C#, although I'm less familiar with the syntax.

For the cases where your classes don't exactly follow the same syntax convention, SFINAE helps you by letting you provide several variants - if one fails, the compiler will pick the next one and try with that. Using shims, you can limit the number of variants by providing one generic function that uses appropriately defined shims to both set and get each coordinates for all existing classes.

Carl Seleborg
thanks for the shim link, I hadn't heard that term before. I think that's a step in the right direction. I'd rather shy away from the templated function, since the interfaces to these classes aren't necessarily standard (for example I can't assume the [] operator is defined).Some of these terms led me around to this though:http://en.wikipedia.org/wiki/Adapter_patternI suppose I could apply that pattern here.
Gabe
wow, SFINAE seems pretty powerful. Is that a standard C++ feature? If it's handled the same by gcc and microsoft, then that could be the best way to handle this.
Gabe
Gabe
+1  A: 

I think that the solution of Carl is the simpliest in C++. The problem with the adapter pattern is that the adapted type should be an interface or abstract class or maybe a class with several virtual methods. Typically, matrix don't have these conditions, because a matrix is a Value type, it's not really natural to implement an interface on it. (what I mean by value type is that the equality isn't defined by the identity of the object but by its fields)

If you really want to do this, you can create a IMatrix interface and implement the interface for each adaptee type.

The other solution is to create a canonical type, and create translators to this type foreach versions of Matrix.

These two ways are equivalent in lines of code, but the second one is more intuitive.

Nicolas Dorier
I assume what you mean by a "canonical type" is to just pick one matrix/vector implementation and always translate everything to/from that type. So in the example above, I would translate transformedPoint into some sort of CanonicalVector, then I would translate that into a HyperPoint before passing it to the KdTree. So the CanonicalVector would implement FromFixedPointType() and ToHyperPoint(). Does that sound right?
Gabe
Yes it's what I meant, without canonical type with n types you have n! translations to code. With a canonical you have only 2n translations to code.
Nicolas Dorier
Well put. Thanks!
Gabe
I've made a mistake, without canonical type there is f(n) = f(n-1) + 2(n-1) translation to code, it doesn't change my point though.
Nicolas Dorier
A: 

Try looking for the term ducktyping. If you find a good solution please post it here, i have the same problem in C#, i have to manually cast between different Vector-types for different libraries even if the Vector-classes all have the same functionality :(

Although I've never actually used it before, I believe you can leverage TypeConverter in .NET. Maybe I should try to mimic that in C++. See this article for more info: http://msdn.microsoft.com/en-us/library/ayybcxe5(VS.71).aspx
Gabe