Boost logo

Boost :

From: Anis Benyelloul (benyelloul_at_[hidden])
Date: 2005-07-02 05:40:01


Geoff Carlton <gcarlton <at> iinet.net.au> writes:
>I'd like a simple, common set of geom classes.

Let's see If I can do something for you ..

> The concept of these traits is a very interesting and clever one,

Thanks !

> but I don't think its useful in practice.

Well, before you say this, let's examine together the problem we are facing.
 What I'm doing here is not just one more point class,
there are already plenty of them ! for example :

template<class T> class point
/// Simplistic (Unrealistic) view of points
{
        public:
        
        point(T x, T y); // Handy ctor
        
        T get_x() const;
        void set_x(T t);

        // ...
        point operator+=(const point& pt);
        point operator-=(const point& pt);

        void normalize();
private:
        T coord[2]; // X and Y in an array
};

This sollution is really acceptable only if :
        - In all your life, all you'll ever need is cartesian points.
        - In all your life, all you'll ever need is cartesian points
implemented that way (in an array).
That is, you are forced to use one representation (cartesian) and one
implementation of that representation
(using the terminology introduced in the geom manual).

For a boost library (that is supposed to be the best you can find), this is not
acceptable. We want more, We want better !

So the idea is here:
        - There is reasonably no single representation (cartesian, polar,
homogenous) of
                points that fits everyone on every project.
        - For every representation, there no single implementation that fits
everyone on every project.
        - A real boost library has to deal with that, it can't just close its
eyes and pretend the whole world only needs
                cartesian points implemented in an array of two elements.
And of course that is not limited to points, other geometric abstractions also
are concerned.
 
> You'd want a simple set of classes,

Simple ? You can't be simple and as general as we want (as I explained above),

> and if they are generically useful then the conversion to library
> variants is simple:
> either construct a new temporary,

I don't want to create a temporary array of 1000 points just to do the
conversion,
I want to work with a compatible array from the start ..

>or even a straight reinterpret_cast for performance.

Not always possible. If the two representation are different you can surley
kiss your reinterpret_cast goodbye.
Example:
        You're using a cartesian point => Library needs polar points or
homogeneous points
        You're using rectangles represented as a corner and a size => Library
needs
                 rectangle represented as opposite corners

That was the problem, traits classes are the sollution ... (more about it in
the manual)

> In particular, the basics are:

In the following I'll present corresponding code using Boost.Geom. Assume that
the following takes effect
#include <boost/geom/point.hpp>
#include <boost/geom/point_xy.hpp> // For the present example I'll use 2D
cartesian points

// Now handy usings
using boost::geom::point_xy;
using boost::geom::point;
 
>1.) Easy definition
> Preferably:
> class point2i; // descended from point2<int>
> void DoSomething(const point2i& mypoint);

typedef point< point_xy<int> > point2i;

void DoSomething(const point2i& mypoint);

>Alternatively:
> template<class T>
> class point2;
>
> typedef point2<int> mypoint2i;
>
> void DoSomething(const point2i& mypoint);

typedef point< point_xy<int> > point2i;

void DoSomething(const point2i& mypoint);

>2.) Easy instantiation
>Definitely:
> point2i pos(1,2);
point2i p=point_xy<int>(1, 2); // Also possible to init with polar data e.g
                           // point2i p=point_polar(3, 3.141592654)

>Ideally (somehow):
> point2i pos2[2] = { { 3, 4 }, { 5, 6 } };

This is also possible, after having written an implementation of points that
uses arrays:

point<point_xy_array> pos2[2]={ {3, 4}, {5, 6} } ; /////...

Actually, I was planning to write such an implementation.

>3.) Very clear class layout
>So we can know when reinterpreting the object is possible.

Actually with Boost.Geom, you'll never have to reinterpret_cast ! For example
if the underlying
library uses BB_POINT, you'll have:

point<BB_POINT> pt;

BB_DRAW_POINT(&pt.impl()) ; // The return type of pt.impl() is BB_POINT&

>4.) Minimum of templates and macros
>Want this to be compile-able across the board, and simple to understand.

Well, not possible if we aim for generality (BTW Boost.Geom makes heavy use of
templeates and about no use of macros
). Besides, do you really need to understand how Boost.Geom is
implemented to use it effectively, I doubt it. Also, I don't think we should
limit our imagination just because
compiler such and such doesn't yet support (such a usual thing as) partial
template specialization.

>5.) Basic methods in class
>Length(), LengthSq(), Normalise(), etc

pt.rho(); // Access to the distance between the origin and pt

pt.rho()=1; // Set the distance to 1 i.e normalizing ...
// and many more

>6.) Set of algorithm functions to operate on these types Similar to STL,
>a separate group of functions.

Hummm.. sounds good. If only you could give some precise examples of
potentially useful algorithms..

-- Anis Benyelloul


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk