Boost logo

Boost :

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


Andy Little <andy <at> servocomm.freeserve.co.uk> writes:

>template<typename ValueType>
>struct rectangle{
> xy_pair<ValueType> position;
> xy_pair<ValueType> size;
>};

Nice ! I like the idea of a meaningful neagative size.

>I generally only have a very few low level conversion functions where my user
>types are converted to the platform dependent types for output.
>I would guess that the system call to the graphics device is much more
>expensive than the single conversion so the cost is small,( but I havent tested
>this theory)

Ok ! Consider this: We are writing a 2D Game using SDL. Each time we
move something on the screen we must remember its last and new position (two
rectangles)
so that we can redraw that area and update the screen (we call this, a dirty
rectangle
mechanisim) So at each frame we construct the region of the screen that has to
be redrawen
before calling SDL_UpdateRects to update the screen. The region is constructed
60 times per second (this the refresh rate of most screens), do you think
that the game writer will want to convert a vector<rectangle> (whose size may
vary
between 0 and 100) into the corresponding
vector<SDL_Rect> 60 times per second ? And remember there is far more stuff to
be done in this 1/60 of a second.

>I prefer using my own graphics primitives for various reasons.
>For example using Windows GDI output range is limited to a 16 bit integral
>value. I perform to work using (underlying) doubles, convert to the device
>coordinate system and finally clip the resulting value to the device
viewport
>and only then cast to an integer to perform the raw output using the
>implementation defined call. In practise I never use the graphics platform
>defined types directly.

Fair enough ! But what if you're actually satisfied with 16 bit integrals ?
Do you still want to do conversions ?

>Yes , I see the point of the wrapper , but OTOH
>
> point_polar p1 = point_xy();
> point_xy p 2 = p1;
>
> should also work.

I beg to differ. Implementation types were never ment to be used as such, they
were
designed to be wrapped. Indeed, for sometime I resisted the following idea :

template<class T>
struct point_xy
{
        friend class point_traits< point_xy<T> >;
        point();
        point(T x, T y);

        private:
                T x, y;
};

That is only the traits class specilization need to know about members of
point_xy.

I really can't see why you'd want to use (the simple, featureless) point_xy
when you
have (the powerfull, general) point<point_xy>.

For example if you use point_xy for your project and after 2 months you realize
that polar points are more suitable, lots of stuff will need to be changed for
point_xy
provides direct access to its x and Y (only), while polar_point provides RHO
and THETA (only)
, but point<point_xy> *and* point<polar_point> do provide X, Y, Z, RHO, THETA,
and PHI !!!

>Sure ...Assuming the above two types
>
> point_polar.x();
> point_xy.x();
>
> point_xy. phase_angle();
> point_polar.phase_angle();
>
> IOW each has the same interface.

Ok, but you seem to be only considering implementation types provided by
Boost.Geom. Of course we
could do that, but this is only because we have complete control over point_xy
and point_polar.
Now what about std::complex<> ? Do you think you can arrange to be able to
write:

typedef std::complex<float> point;

point pt;
pt.x()=10;
pt.phase_angle()+=3.141592654;

What about POINT, QPOint, XPoint, XYZ_Point_XYZ ? So no, giving a bunch of
types the same
interface is quite not the same as using traits. For one good reason: You don't
have
control over all the types you'd like to give the same interface. Using traits
you can
effectively call x() on an std::complex<> ;

geom::point< std::complex<double> > pt;
pt.x()+=0.3; // Et Voila !

So, in order to keep consistency we don't provide complicated members in
implementation
types, we put them in wrapper classes.

>> Note that :
>> - You take benefit of the notaional convinience of geom::box
>> - geom::box is a zero cost wrapper, using it does not create
>> additional overhead as such.
>> - You don't have to convert between geom::box<TG_RECT> and
>> TG_RECT, or more precisely, the conversion is zero cost.
>> And that is not specific to trendy_graph, if you also work with
>> FastGraph you'll be able to wrap FG_Rectangle in a geom::box and
>> enjoy the same interface as with geom::box<TG_RECT>, while still be
>> able to turn a geom::box<FG_Rectangle> into a FG_Rectangle at no cost
>> ! You learn one interface (that of geom::box) and you keep using it
>> regardless of the underlying graph API, while not having to pay in
>> efficiency, Isn't wrapping other libraries wonderful ?

>Well its certainly a trick that this library plays but the wrapping is very
>limited (because the underlying tyopes are exposed in the template parameter),

What ? I don't see in what it is limited. If you don't want to expose the
templete
parameter, use typedefs !!

typedef geom::point< geom::point_xy<float> > point;

// Now forget about Boost.Geom and use point !

POINT convert_to_POINT(const point& pt);

>but how useful is it in practise? How often do you need to convert?

60 times per second converting 100 rectangles is overkill.

>I prefer to
>hide the platform dependent points behind a 'standard' type which works at a
>level above the output device towards which these other types seem to be
>geared. However I dont think that your library rules this out.

It doesn't. If you want close integration use point<GG_Point_2D> if you want
platform independent types use point< point_xy<double> > !

> You could even
>specialise it for eg double parameter..

And could you tell me about the possible benefits we'd reaping of this ?

>The point I'm trying to make is that its much easier to do this if the
platforms
>own types are not exposed at all.

Don't get why...:(

>OK.. take a look at the angles in pqs. Using them you can use both degrees and
>radians interchangeably. degrees is more human friendly IMO , while radians is
>better for math of course. :-)

This certainly is a good idea. Now if only your library gets accepted in
Boost ...

>> U={(x,y,z) in IRxIRxIR such that z=0};
> [...]
> Not too good on the math theory . IOW I dont understand this :-(

Don't be afraid by technical math terms like ``automorphism'' ! (they're merely
good enough for impressing girls .. ;-) ) It only means that there is a
bijection
between U and IRxIR , i.e to every element of U corresponds one and only one
element of IRxIR, and to every element of IRxIR corresponds one and only one
element
of U. So IRxIR and U are (mathematically) the same.

[...]

>Unless you provide ready made output facilities, no one will use the library
>IMO.
I disagree. People already have/know output facilities optimized for thier
platform
and they can easily use them to draw geom::boxes.

> It also gives a chance to prove how cross-platform the library really is.

It is already cross platform. You can plug almost anything in a geom::point<>

> template <
> typename GX
> >
> void redraw(GX & gx)
>{
> pt p0,p1,p2,p3; // some points
> line L1(p0,p2); /
>
> polyline poly0;
> poly0 += p0, p1,p2,p3; // assign values
>
> polygon poly1;
> poly1 += p0, p1,p2,p3;
>
> bezier bez( L1, line(p1,p3));
> // gx is some graphics output device
>
> gx << L1 << poly0 << poly1 << bez;
> }

Wow !!! You got far away my friend !! We aren't writing a graphical library, we
are writing a "Geometric Primitives Library". If you already have some graphical
library feel free to use it to draw geom::points, geom::bezier ... But I doubt
it
is the purpose of Boost.Geom to provide things like GraphContext or
Window::handle_event(const MouseEvent&)!

Of course if someone wants to do this (think of it ! a Boost-Quality cross
platform GUI/Graph library)
Boost.Geom could serve as a "base", but it shouldn't itself be the graph API.
Let's divide the problem
into small pieces and deal with each spearatly.

>Hopefully some day sooner or later I plan to redo it suitable for boost and of
>course will announce the fact too :-)

Ok I'll wait :).

-- Anis Benyelloul


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