Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-01-01 23:38:13


Probably I'm too late with my thoughts about the whole Dave Abrahams' idea
of boost Window toolkit and the topic seems to be closed by now, but I
still want to discuss a small part of this not-yet-existing toolkit -
geometry classes like point, rectangle and so on.
In fact, a long time before Dave have posted his proposal - about 3 months
ago, at the first time I took a look at boost.org - I thought about such
classes as an ideal candidates to the boost library. As Paul Moore said,
they are indeed sort of classes that get reinvented over and over and I
think it's time to try to summarize experience we have by now with them (I
think everybody in this group have written his own version of them, right?
;) and to present some initial version which eventually may become a
standard - as it happens with 'string'. So I've took a courage to make the
first contribution. It's really a very raw version, so any constructive
feedback is welcome. And actually there are already a few open questions I
want to discuss here:
1) What about the 'problem of one pixel'? Do coordinate values have to be
treated as coordinates of points or as coordinates of grid lines between
points? E.g. what pair of points describes the following rectangle:
(1,1)-(4,3) or (1,1)-(5,4)?
_________
|_|_|_|_|_|_|
|_|#|#|#|#|_|
|_|#|_|_|#|_|
|_|#|#|#|#|_|
|_|_|_|_|_|_|

The answer to this question determines the implementation of many
rectangle's methods, such as width() ( 'return right - left + 1' or 'return
right - left' ?). Native coordinate systems on many platforms seem to agree
upon the second model - coordinate values are treated as coordinates of grid
lines between points, but definitely there are systems which use the first
approach. We can choose one of them and delegate dealing with the problem to
conversion operators from our classes to native geometry types, but does
this solve the problem? I mean would all people accept this solution? What
if some of them already have a platform-independent code that relies on a
particular method which may be different from our choice? Probably they'll
decide not to use the boost geometry classes - even if they are still
adding a new code to their project. Otherwise they ought to remember what
kind of classes they are using every time when they work on a particular
code fragment.
At present time my implementation uses the second approach - as the most
common one - but that are you think about this question?

2) Do we need a separate 'size' class, or we want to use 'point' everywhere
instead it? Necessity for 'size' may seemed non-obvious for those who always
worked only with 'point' and 'rect', but if you only tasted the 'size' you
may feel it is quite naturally to have yet another geometry class. For
example, if you have no a 'size' class and you construct a rectangle from
two points, it is not clearly how the constructor uses these points - as
left-top and right-bottom coordinates or as left-top coordinates and sizes
of rectangle sides. And what is more, you can't even write two such
constructors - one for the first behavior and other for the second - you
have to choose one of them. Another example is 'size()' operation of a
rectangle class - it seems for me at least discouraging to have this method
return 'point' instead 'class size'. Yet other case when it feels quite
reasonable to distinguish point and size concepts is rect::operator +=. If
we have both 'point' and 'size', we may have two versions of this operator
(a) rect::operator += ( const point& p ) will move a rectangle origin, but
not change its size and (b) rect::operator += ( const size& s ) will change
a rectangle size, but not move the rectangle origin point. Finally my
version of geometry classes have a 'size' class. But I still have doubts
about this question. Your thoughts?
3) Do we allow a public access to members of geometry classes, or we need to
hide them behind accessors? I've been always using access wrappers, but for
many people it may seemed quite ugly and uncomfortable to write rect.top()
+= 10 (or rect.origin().x() += 10). And that about names of either wrappers
or members? Must we name them 'x', 'y' for point and 'left', 'top',
'right', 'bottom' for rectangle or, say, 'col', 'row' and 'origin().col()',
'origin().row()', 'corner().col()', corner().row()' or something else? By
the way, if we will use access methods, we can to present all of name
variants. But is it acceptable?
4) Do we want to see operators like += in both point and rectangle classes
as member template functions, or we would prefer to make them an ordinary
functions with 'const self&' argument and to provide a template copy
constructor for conversions like point<long> to point<double> ? E.g. what we
would prefer:
a) template<class T>
template<class U>
point<T>& point<T>::operator +=( const point<U>& offset );
or
b) template<class T>
template<class U>
point(const point<U>& offset );
 and
template<class T>
point<T>& point<T>::operator +=( const point<T>& offset );
Or we would like a combination of both approaches - a template copy
constructor and template member operators like +=? ( current implementation
doesn't support either of these methods because my compiler - MSVC 6.0 - can
't deal with member templates inside template classes ).

Anyway, I am posting my current implementation as proposal...
-Alexy




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