Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2005-06-29 13:54:50


"Anis Benyelloul" <benyelloul_at_[hidden]> wrote
> Andy Little writes:
>
> <your_suggestion>
> struct point { int x,y; };
> struct rectangle { int x, y, width, height; };
> </your_suggestion>

FWIW My current rectangle looks something like:

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

position can be at any corner dependent on the sign of size.x and size.y.

> Well, if you insist on using rectangle (instead of TG_RECT) you'll end
> up creating an array of rectangle, and converting it into the
> corresponding array of TG_RECT that you can pass to
> TG_Update_Screen. This is overkill. If you care about performances
> you'll just use TG_RECT in your own code.

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) 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.

>>Ok. I understand the use of a common type for cartesian and polar
>>coordinates.
>>Alternatively these two types could be provided as complete useable types,
> with
>>a common interface.
>
> I'm not sure I get it, could you name the "types" you're talking
> about ?

Sure eg :
        point_xy<value_type>
 and
        point_polar<value_type>.

>>A viable alternative to the wrapper is simply to provide a
>>conversion from one to the other type.
>
> A as a consequence of traits&wrappers the conversion is already
> provided:
> <code>
> point<point_polar> pt_p=point_polar(1, 3.141592654); // Polar
> point<point_xy> pt_c=point_xy(10, 20); // Cartesian
>
> pt_p=pt_c;// Conversion !!!
> </code>

Yes , I see the point of the wrapper , but OTOH

    point_polar p1 = point_xy();
    point_xy p 2 = p1;

    should also work.

>>Specialising the traits class looks to be
>>nearly the same work as writing these from scratch with a common
>>interface.
>
> I don't get that either, sorry... Could you explicit your thoughts a
> bit ?

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.

[...]

> 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),
but how useful is it in practise? How often do you need to convert? 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. You could even
specialise it for eg double parameter..

>>I would want
>>precisely defined semantics on the parameters of a point. For example I would
>>expect the semantics of float versus integer value_types to be defined
>>separately. Allowing use of user defined point systems would appear to make
>>this type of control of the specification much more difficult, if not
>>impossible.
>
> Well, putting the exact and precise requirements imposed on
> geom::point<>'s template parameter and on the corresponding traits
> specialization is hard, very hard, maybe too hard for me. But I'll
> give it a try. Thanks for pointing this out.

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.

>>Not sure what units angles are in. Is it degrees or radians? radians is my
>>preference.
>
> The standard C++ library (std::sin, std::cos, .. etc) speaks in
> radians, so I do.

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. :-)

> What is the connection between your library and boost, do you intend
> to have it accepted in Boost ? .. I'll make sure to give it a try ...

The intention is to rewrite it using the boost libraries such as Boost.Typeof
and maybe the examples in the mpl book.

>>I strongly disagree with the statement in the documentation:
>>
>>" Indeed, a ``2D point'' is just a 3D point whose implementation doesn't
>>actually reserve memory space for a Z attribute."

[..]

> Consider this: (let IR be the set of all real numbers)
> IRxIR is a 2D space. And IRxIRxIR is a 3D space.
> Let U={(x,y,z) in IRxIRxIR such that z=0}
> Now we can find an automorphism that maps U to IRxIR. That is, even
> though U seems part of IRxIRxIR (3D), it is mathematically
> indistinguishable from IRxIR (2D). So U is a part of IRxIRxIR (3D), but
> at the same time *it is* IRxIR (which is 2D). See how the "notion of
> another dimention" depends on the point of view ...

Not too good on the math theory . IOW I dont understand this :-(

[..]

> For homogeneous stuff, one can easily write a point implementation, say
> point_xyzq that stores a forth attribute. But about matrix
> transformation,... well, I'm not sure if there should be somekind of
> geom::matrix.. For example, If your're doing 3D games using OpenGL you
> already have some matrix manipulation primitives like glMultMatrix(),
> do we want to wrap glMultMatrix, to concurrence it or not care about
> it at all ? (IMO the latter !)

OpenGL is slely geared towards output isnt it?. I havent used it but I believe
that these functions use persistent state across calls, so it might be awkward
to use. Nevertheless OpenGL might be a good example to get ideas from.
Especially the separate translate, rotate etc matrix functions.

>>The box here is useful for a GUI viewport or window, an attribute of the
>>current output device. IMO Its a mistake for a geometry library to get
>>involved
>>with this low level stuff too early. Geometrically a box is a 2D region
>>bounded
>>by geometric *1* lines, with no guarantee of its attitude. Why not start
>>with
>>the most primitive concepts, eg geometric points, lines, circles arcs, curves
>>and regions?
>
> Exactly what I was thinking.

:-)

[..]

>>That said, there should be some form of mechanism for graphical output on
>>various platforms/ devices, but again without this affecting the core geometry
>>library. generically this requires some means of converting points between
>>various coordinate systems.
>
> Humm .... such a mechanism should be, but I doubt it is really up to
> Boost.Geom to provide it. The user is free to use any output means
> available, for example if [s]he is using fast_graph:

Unless you provide ready made output facilities, no one will use the library
IMO.
It also gives a chance to prove how cross-platform the library really is.

> <code>
> geom::box<FG_Rectangle> bx;
> // Play with bx ....
>
> // Draw bx
> FG_DrawRectangle(&bx.impl(), FG_Forground, FG_MAKE_COLOR_RGB(0x2,
> 0x22, 0x32);
> </code>

Bearing in mind that we have radically different views my current thinking more
aong the lines of :

    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;
   }
// gx takes care of all the implementation/platform dependent stuff.
Of course making all these entities objects rather than output functions helps
things such as serialisation etc.(Other issue I have is need for 'active
entities' which need eg on_grab () functions, but I guess that this is more GUI
oriented stuff, nevertheless the object approach of the library might help
this).

>>Sorry for all the criticism. As you may gather I have my own ideas on what I
>>want from a geometry library... looking forward to hearing your views ...
>
> No, don't be sorry. With your suggestions, opinions and criticism
> you're helping improve my work (& knowledge), thanks a lot.
>
>>as opposed to lines which have colour and thickness. These attributes,
>>though required for output are not necessary from a geometric viewpoint
>
> I totally agree !

OTOH providing these properties needs to be considered also for output purposes.
Again I favour an object approach where each entity holds its own eg colour
information. This means that less state needs to be kept in the (proxy for the)
output device.

> PS: I'll have a look at your library and tell you my impressions. But
> where should I send them ? Private mail ? Boost mailing list ?
> Anywhere else ?

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

Andy Little


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