HELP SIM_PICAGENT                                  Aaron Sloman Feb 1999

Section on multiple windows needs improvement

LIB SIM_PICAGENT
Composite simulation and pictorial objects and agents


CONTENTS

 -- Introduction: agents and objects in two spaces
 -- Two sets of coordinates
 -- -- Derived mixins
 -- The mapping between the simulated world and the picture
 -- Simulation and picture coordinates
 -- -- sim_set_coords(obj, x, y);
 -- -- Accessing the simulation and picture coordinates
 -- -- . sim_coords(obj:sim_multiwin_mobile) -> (x, y);
 -- -- . rc_coords(obj:sim_multiwin_mobile) -> (x, y);
 -- -- Methods for altering locations (after drawing)
 -- -- . x, y -> sim_coords(obj:sim_multiwin_mobile)
 -- -- . rc_move_to(obj:sim_multiwin_mobile, x, y, drawmode)
 -- -- . sim_move_to(obj:sim_multiwin_mobile, x, y, drawmode);
 -- Other utilities
 -- -- sim_distance(obj1:sim_multiwin_mobile, obj2:sim_multiwin_mobile) -> num
 -- -- sim_transxy_to_pic(x, y) -> (x,y)
 -- -- sim_transxy_from_pic(x, y) ->(x, y) ;
 -- Other libraries used
 -- Some examples of pictures in more than one window
 -- Index

-- Introduction: agents and objects in two spaces ---------------------

This library defines new mixins based in the RCLIB graphical extensions
to RC_GRAPHIC (See HELP RCLIB), and uses those mixins to define a new
collection of mixins in combination with the classes sim_object and
sim_agent. This makes it possible to create simulated objects and
agents which have depictions that are movable both in a simulated 2D
world and also in a 2-D picture (created using rc_new_window_object).
Such depictions are also mouse sensitive, so that all the mechanisms
described in HELP * RCLIB and HELP * RC_LINEPIC are applicable.

In addition it is possible to have the same thing located in two or more
windows, where the windows may correspond to different portions of the
2-D simulation world, and may have different scales.

We use this class for the windows:

define :class sim_picagent_window; is rc_window_object;

    slot sim_picframe =
        consvector(#| sim_picxorigin_def, sim_picyorigin_def,
            sim_picxscale_def, sim_picyscale_def |#);

enddefine;

The sim_picframe slot determines how the picture coordinates correspond
to simulation coordinates.

-- Two sets of coordinates --------------------------------------------

The top level mixin defines objects which have two sets of coordinates,
one pair for pictures (rc_picx, rc_picy) and one pair for the simulated
2D world (sim_x, sim_y). The former are not represented directly, but
computed by methods.

define :mixin sim_multiwin;
    ;;; The basic mixin linking simulations and drawings
    ;;; for linked picture objects
    is rc_keysensitive rc_selectable rc_linepic;

    ;;; initially known to contain no pictures
    slot rc_pic_containers == [];

    /*
    ;;; see LIB RC_LINEPIC
    ;;; These two will be simulated, derived from sim_x, sim_y
    slot rc_picx == 0;
    slot rc_picy == 0;
    */

    ;;; Two sim coordinates for location within a simulation
    slot sim_x == 0;
    slot sim_y == 0;

    ;;; Two sim coordinates for old location within a simulation
    slot sim_oldx == false;
    slot sim_oldy == false;
enddefine;


As long as the picture coordinates are not manipulated directly, but
only using the methods described below, the picture and world
coordinates will be kept in correspondence.

-- -- Derived mixins

define :mixin sim_multiwin_static; is sim_multiwin;
    ;;; for unmovable linked picture objects

    ;;; by default these are not draggable
    slot rc_drag_handlers = { ^false ^false ^false};
enddefine;

define :mixin sim_multiwin_mobile; is sim_multiwin rc_linepic_movable;
    ;;; no new slots
enddefine;

;;; Descendants of sim_multiwin_static (objects and agents)
define :mixin sim_immobile; is sim_multiwin_static sim_object;
    ;;; objects which can be drawn and selected, but not moved
    ;;; No internal processing mechanisms, by default
    slot sim_rulesystem == [];
    ;;; other slots inherited from sim_object
enddefine;

define :mixin sim_immobile_agent; is sim_multiwin_static sim_agent;
    ;;; Agents which can be drawn and selected, but not moved
    ;;; other slots inherited from sim_agent
enddefine;


;;; Descendants of sim_multiwin_mobile (objects and agents)

define :mixin sim_movable; is sim_multiwin_mobile sim_object;
    ;;; other slots inherited from sim_object
enddefine;

define :mixin sim_movable_agent; is sim_multiwin_mobile sim_agent;
    ;;; otherwise slots inherited from sim_agent
enddefine;



-- The mapping between the simulated world and the picture ------------

The instances of the new classes have locations in both a 2-D simulation
space and in the 2-D picture. Each space has its own coordinate frame.

The mapping between the two spaces is defined by vector of four numbers
stored in the window object's slot sim_picframe, corresponding to
xorigin, yorigin, xscale, yscale.

When the vector is {0 0 1 1} the values map the simulation space
directly onto the picture window, with the origin coincident, and the
scales the same.

To move the simulation origin to a point 20 pixels down and 30 to the
right of the rc_graphic origin, and expand the picture size by 50%,
while reversing the direction of the y axis, use

        {20 30 1.5 -1.5}

This will not change the sizes of the drawn representations of objects,
only the distances between them (and the speed with which they move
across the screen).

In order to change the size of depicted objects alter rc_xscale,
rc_yscale in the picture window, e.g. by setting up the window object
with a suitable scale. (See HELP RCLIB/rc_new_window_object)

-- Simulation and picture coordinates ---------------------------------

To make sure that the simulation coordinates and the picture coordinates
are always in step it is important not to alter them directly, but
always to use standard methods.

-- -- sim_set_coords(obj, x, y);

In order to initialise an object before it is drawn, use sim_set_coords,
which takes an object or agent and its coordinates in the simulation
space and, sets the coordinates in both the simulation space and the
picture space.

-- -- Accessing the simulation and picture coordinates

-- -- . sim_coords(obj:sim_multiwin_mobile) -> (x, y);

The method sim_coords returns the current simulation coordinates of its
argument.

-- -- . rc_coords(obj:sim_multiwin_mobile) -> (x, y);

The method rc_coords returns the current picture coordinates of its
argument.

-- -- Methods for altering locations (after drawing)

-- -- . x, y -> sim_coords(obj:sim_multiwin_mobile)

To specify a new location in simulation space, for an instance of a
movable class, use the updater of sim_coords, as in:

    x,y -> sim_coords(obj);

This will also automatically change the picture coordinates, and cause
the object to move on the screen.

-- -- . rc_move_to(obj:sim_multiwin_mobile, x, y, drawmode)

The method rc_move_to defined in HELP RCLIB/rc_move_to moves the object
to the specified location in picture coordinates (showing the move if
the final argument is true, and showing a trail if it is the word
"trail"). If it is false, nothing is shown.

It also automatically updates the simulation coordinates, if applied to
a sim_multiwin_mobile object.

The method rc_move_by(pic:rc_linepic_movable, dx, dy, drawmode)
can be applied to these objects. It will invoke rc_move_to which will
behave as described.


-- -- . sim_move_to(obj:sim_multiwin_mobile, x, y, drawmode);

This is equivalent to the following

    x, y -> sim_coords(obj);

except that the final argument gives extra control over what happens on
the screen, as in rc_move_to. Note that here x and y are in simulation
coordinates, not screen coordinates.


-- Other utilities ----------------------------------------------------

-- -- sim_distance(obj1:sim_multiwin_mobile, obj2:sim_multiwin_mobile) -> num

Returns a number representing the distance between the two objects.

-- -- sim_transxy_to_pic(x, y) -> (x,y)

Given simulation coordinates return the picture coordinates, using the
frame variables described above.

-- -- sim_transxy_from_pic(x, y) ->(x, y) ;

Gven x,y in picture coordinates, return simulation coordinates.

-- Other libraries used -----------------------------------------------

We assume that lib sim_agent has been compiled, and that its classes
sim_object and sim_agent have already been defined. Likewise we assume
that several of the rclib libraries have been defined.


-- Some examples of pictures in more than one window ------------------

uses rclib;
uses simlib;
uses sim_picagent;


define :class testpic;
    is sim_movable;
    ;;; slot rc_pic_lines = [SQUARE {0 0 20}];
    ;;; use RSQUARE to make it work upside down also
    slot rc_pic_lines = [WIDTH 2 RSQUARE {-10 10 20}];
    slot rc_mouse_limit = 10;
enddefine;

define :class statpic;
    is sim_immobile;
    ;;; slot rc_pic_lines = [SQUARE {0 0 20}];
    ;;; use RSQUARE to make it work upside down also
    slot rc_pic_lines = [WIDTH 4 RSQUARE {-10 10 20}];
    slot rc_mouse_limit = 10;
enddefine;

define newpic(x, y, label, windows) -> pic;

    instance testpic;
        sim_x = x;
        sim_y = y;
        rc_pic_strings = [{-4 0 ^label}];
    endinstance -> pic;

    rc_add_containers(pic, windows);

enddefine;

define newstatic(x, y, label, windows) -> pic;

    instance statpic;
        sim_x = x;
        sim_y = y;
        rc_pic_strings = [{-4 0 ^label}];
    endinstance -> pic;

    rc_add_containers(pic, windows);

enddefine;

vars
    win1 =
        rc_new_window_object(20, 5, 250, 250, true, 'win1',newsim_picagent_window),
    win2 =
        rc_new_window_object(300, 5, 250, 250, {125 125 1 1}, 'win2',newsim_picagent_window),
    win3 =
        rc_new_window_object(580, 5, 500, 500, {250 250 2.0 -2.0} , 'win3',newsim_picagent_window),

    windows = [^win1 ^win2 ^win3],
;

;;; vars windows = [^win1];

{0 0 1 -1} -> sim_picframe(win3);
/*
applist(windows, rc_kill_window_object);

rc_current_window_object =>
win1 -> rc_current_window_object;
win2 -> rc_current_window_object;
win3 -> rc_current_window_object;
*/
vars
    p1 = newpic(50, 50, 'p1', windows),
    p2 = newpic(100, 100, 'p2', windows),
    p3 = newpic(-100, -100, 'p3', windows),
;

;;; now try moving the objects in different windows.

win1.sim_picframe=>

vars x,y, vec = sim_picframe(win1);;
for x from -100 by 1 to 100 do
        x -> vec(1); x -> vec(2);
;;;     1.0+x/600 ->> vec(3) -> vec(4);
        rc_start();
        rc_redraw_window_object(win1);
        syssleep(1);
endfor;

rc_redraw_window_object(win3);

p1 =>
p1.sim_coords =>
p1.sim_x =>
p1.rc_picx=> p1.rc_picy=>
p1.rc_coords =>
p1.sim_oldx,p1.sim_oldy=>

win1.sim_picframe=>

p2 =>
p2.sim_coords =>
sim_move_to(p1,100,-40,true);
rc_move_to(p1,100,-40,true);
rc_move_to(p1,-100,-40,true);
rc_undraw_linepic(p2);
rc_draw_linepic(p2);
sim_picframe(win1) =>
sim_picframe(win2) =>
sim_picframe(win3) =>
rc_yscale =>
sim_picyscale =>
rc_current_window_object =>
rc_active_window_object =>
rc_active_window_object -> rc_current_window_object;
rc_move_to(p3, -10, 10, true);
rc_move_to(p3, -100, 100, true);
rc_move_by(p3, 5,-5, true);

sim_move_to(p2, -100, 100, true);
rc_move_to(p3, -100, 100, true);

vars
    s1 = newstatic(0, 100, 'a', [^win1]); ;;; [^win1 ^win3]);
vars
    s2 = newstatic(0, -100, 'b', [^win2 ]),
;
rc_remove_container(p2, win3);
rc_remove_container(p2, win2);
rc_remove_container(p2, win1);

p2.rc_pic_containers =>


issim_multiwin_static(s1) =>
rc_add_container(s1, win2);
rc_add_container(s2, win3);

p2 =>
p2.rc_pic_containers =>
win3 =>
{0 0 -1 -1} -> sim_picframe(win3);
{0 0 0.5 0.5} -> sim_picframe(win3);
win3 -> rc_current_window_object;
;;; clear the window
rc_start();
;;; Redraw it
rc_redraw_window_object(win3);

rc_add_container(p2, win3);
win3.rc_window_contents ==>
p2 =>

;;; add it normally to win1
rc_add_container(p2, win1);
rc_add_container(p2, win2);


applist(windows, rc_kill_window_object);


-- Index --------------------------------------------------------------

 define vars procedure sim_transxy_to_pic(x, y, frame) /* -> (x,y) */;
 define vars procedure sim_transxy_from_pic(x, y, frame) /* ->(x, y) */;
 define :class sim_picagent_window; is rc_window_object;
 define :mixin sim_multiwin;
 define :method rc_coords(obj:sim_multiwin) -> (x, y);
 define :method rc_picx(obj:sim_multiwin) -> x;
 define :method rc_picy(obj:sim_multiwin) -> y;
 define :method sim_coords(obj:sim_multiwin) -> (x, y);
 define sim_set_coords(obj, x, y);
 define :method sim_distance(obj1:sim_multiwin, obj2:sim_multiwin) -> num;
 define :mixin sim_multiwin_static; is sim_multiwin;
 define :mixin sim_multiwin_mobile; is sim_multiwin rc_linepic_movable;
 define :method updaterof sim_coords(x, y, obj:sim_multiwin_mobile);
 define :method print_instance(pic:sim_multiwin_static);
 define :method print_instance(pic:sim_multiwin_mobile);
 define :mixin sim_immobile; is sim_multiwin_static sim_object;
 define :mixin sim_immobile_agent; is sim_multiwin_static sim_agent;
 define :mixin sim_movable; is sim_multiwin_mobile sim_object;
 define :mixin sim_movable_agent; is sim_multiwin_mobile sim_agent;
 define :method rc_draw_linepic(pic:sim_multiwin_static);
 define :method rc_draw_linepic(pic:sim_multiwin_mobile);
 define :method rc_draw_oldpic(pic:sim_multiwin_mobile);
 define :method rc_move_to(obj:sim_multiwin_mobile, x, y, drawmode);
 define :method sim_move_to(obj:sim_multiwin_mobile, x, y, drawmode);
 define :method rc_pictures_selected(win_obj:sim_picagent_window, x, y, findone) -> num;
 define :method rc_add_containers(pic:sim_multiwin, windows);
 define :method rc_add_containers(pic:sim_multiwin_mobile, windows);
 define :method rc_add_container(pic:sim_multiwin, win_obj);
 define :method rc_add_container(pic:sim_multiwin_mobile, item);
 define :method rc_remove_container(pic:sim_multiwin_mobile, win_obj);


--- $poplocal/local/sim/help/sim_picagent
--- Copyright University of Birmingham 1999. All rights reserved. ------
