Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2004-09-13 11:17:00


Hi,

Recent discussions on boost have talked about GUI's in quite technical
terms, windowing etc. Another part of the abstraction is simply that of
providing an area for drawing on. The code below is a simple example of what
I mean. The "drawFunction" is meant to be like a graphics version of a
main() function .( Note that there should ideally be no DeviceHandle visible
to the "drawFunction". The DeviceHandle should be wrapped in the GX object,
passed to the function so some of the impl is poking through here in form of
the gx.line_to etc functions 'hdc' argument. Its early days.)

The display output from the function is available at:

http://www.servocomm.freeserve.co.uk/Cpp/physical_quantity/source/capacitor_time_curve.gif

Behind the function there is of course a windows app, (built using WTL in
this case), though the function could could be invoked on any widget, any
operating system ,screen or printer or any device,,, even (say) an
oscilloscope with suitable exposure of the x, y type traits of the GX object
:-)

Note that the use of the unit'ed lengths eg length:::mm provides the key to
the success of the abstraction. If (say) doubles were used, one would need
to provide (Somehow) the information as to what those values represent. here
it is encoded in the type. (And a note to Java programmers... The same
scheme is entirely possible in Java too ). The other useful device is the
"morph" object, which is used to morph time and voltage into lengths in this
example. However it can be used on any two types that can be divided by one
another.

There arent many primitives yet, only lines which makes the function a bit
wordy as it stands, but the intention is to make lines, rects etc available
which can be used to build more complex objects which can be sent to an
output "graphics stream".

... and then the "three_d" namespace ;-)

regards
Andy Little

///////////////

#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

/*
    draw the voltage/time discharge curve for a capacitor
*/

#ifndef PQS_TWO_D_VIEW_ABSTRACTION_HPP_INCLUDED
#define PQS_TWO_D_VIEW_ABSTRACTION_HPP_INCLUDED

#include "pqs/ct_quantity/operations/morph.hpp"
#include "pqs/pqs.hpp"

namespace pqs { namespace two_d{

    template <typename GX, typename DeviceHandle>
    inline
    void drawFunction(GX & gx, DeviceHandle hdc)
    {
        // vect<X,Y> is a general purpose (x,y) container
        // for coords sizes etc
        typedef vect<length::mm> pt;

        // set up size of drawing area in world coordinate sizes
        // This can be scaled and scrolled by the other layers
        // for output on a device
        // world coordinates as used here
        // are the top layer of the graphics view
        gx.max_position() = pt(length::mm(180),length::mm(170));
        gx.min_position() = pt(length::mm(0), length::mm(0));
        // set up border
        length::mm const border(20);

        // set up a drawing rectangle for the graph
        // of voltage / time
        pt draw_rect;
        draw_rect.x() = gx.max_position().x() - 2 * border;
        draw_rect.y() = gx.max_position().y() / 2 - border;

        // move origin to (0,0) on graph
        gx.set_origin(border,border);

        // draw a border round the graph
        gx.move_to(hdc,length::mm(0),length::mm(0));
        gx.line_to(hdc,draw_rect.x(),length::mm(0));
        gx.line_to(hdc,draw_rect.x(), draw_rect.y());
        gx.line_to(hdc,length::mm(0), draw_rect.y());
        gx.line_to(hdc,length::mm(0),length::mm(0));
        gx.text_out(hdc,length::mm(20),
            draw_rect.y() - length::mm(10),
            "Capacitor Time Curve" );

        // capacitor time curve data
        capacitance::uF const C(0.47); //capacitor
        voltage::V const V0(5); //starting voltage across
capacitor
        resistance::kR const R(4.7); // resistance between
terminals
        time_<int>::ms const max_time(20);

        // The "morph" functors convert the source physical-quantities to
target types
        // (here lengths for drawing obviously)
        // with correctly dimensioned scaling value
        // as ctor argument
        morph<length::mm,time::ms> time_x( draw_rect.x() / max_time);
        morph<length::mm,voltage::V> volts_y( draw_rect.y() / V0);

        // draw the graph
        for ( time_<int>::ms t ; t <= max_time; ++t ){

            voltage::V Vt = V0 * std::exp(-t / (R * C));
            if (t == time_<int>::ms(0)){
                gx.move_to(hdc, time_x(t),volts_y(Vt) );
                // "morph" useage
            }
            else{
                gx.line_to(hdc, time_x(t),volts_y(Vt) );
            }
        }
    }

}}//pqs::two_d

#endif


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