|
Boost : |
From: Barend (barend_at_[hidden])
Date: 2008-03-06 06:58:27
Bruno Lalande wrote:
>>> Hopefully these can avoid the boost minefield relating to 'point' types
>>>
>> because trees only work on coordinates (no need to intepret them as "points"
>> per se), and meshes are entirely topological.
>>
>> I don't see anything wrong with a CartesianCoordinateConcept that
>> requires x(), y(), z() along with typedefs or something to that
>> effect. I think the consensus that was reached with the "point"
>> discussion is that too many people want too many different things out
>> of a generic point class, but the algorithms are concerned with very
>> few details of the point class, mainly just "expose x, y, and z, and
>> the types of each" - so don't try to make the perfect generic point
>> class, let people use their own. Just provide algorithms that will
>> work with their point classes, as well as the default (very basic)
>> point class provided by the library.
>>
> This is exactly what I think too. The lack is not about the structure
> (everybody has one and is happy with it) but the algebra applied to them
> (everybody reinvents the wheel on his own structure). Just one point:
> requiring named accessors (x(), y(), z()) would bind us to a specific number
> of dimensions. One very common need is to be dimension-agnostic. In terms of
> structure we already have that : Boost.Tuple. So the idea would be to have
> your CartesianCoordinateConcept requiring templated accessors get<0>(),
> get<1>(), etc... instead, this way the algorithms could work by default on
> tuples.
>
> Bruno
The Geometry Library as we prepare it for Boost/Open Source takes this
approach now, as suggested by Hervé Brönnimann.
The accessors as get<0> are useful, but limited: they do not work in
loops ("expected compile-time constant expression"). So there have to be
also a second accessor get(index).
We have the point now defined like this (named "value").
template<typename T, size_t D>
class point
{
public:
/* ... */
template <size_t K> inline void value(const T& v)
{
BOOST_STATIC_ASSERT(K < D);
_values[K] = v;
}
template <size_t K> inline const T& value() const
{
BOOST_STATIC_ASSERT(K < D);
return _values[K];
}
inline void value(size_t index, const T& v)
{
BOOST_ASSERT(index < D);
_values[index] = v;
}
inline const T& value(size_t index) const
{
BOOST_ASSERT(index < D);
return _values[index];
}
private:
T _values[D];
};
And a derived point like this:
template <typename T>
class point_xy : public point<T, 2>
{
public :
inline const T& x() const { return value<0>(); }
inline const T& y() const { return value<1>(); }
inline void x(const T& v) { value<0>(v); }
inline void y(const T& v) { value<1>(v); }
};
template <typename T>
class point_latlong : public point<T, 2>
{
public :
/* ... */
inline const T& lon() const { return value<0>(); }
inline const T& lat() const { return value<1>(); }
inline void lon(const T& v) { value<0>(v); }
inline void lat(const T& v) { value<1>(v); }
};
(It is presented like this for clarity here, in GCC this doesn't yet
compile and has to be slightly different).
For each derived point class we defined some basic strategies. So for
point_xy there is a strategy pythagoras to calculate the distance, and
for point_latlong there is a strategy greatcircle. For a point_xyz there
would be a 3D pythagoras calculation, or that one could be made
dimension-independant.
In this way the distance algorithm implementation can use the
distance-strategy for the point-type, and the distance algorithm is
itself coordinate free, works for any point. The strategy_traits class
selects the strategy to be used by default. But the library user can
also select an own strategy, for example to calculate more precise
distances with latlong coordinates.
Best regards, Barend
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk