LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

problem displaying in canvas

Hello everybody, (using LabWindows/CVI 6.0)

my program displays in the CANVAS an bitmap (map). A person will walk through this map (from one point to another) and is displayed with a rectangle. When the person change his position, the panel will cleaned and then the map will display again and then the new position of the person.
The functions I used work when I don't use the for-loop. (only one "go-through")
When I use the for-loop, it displays no rectangle until it release the loop and than the program hang-up.



int CVICALLBACK MOVING_FUNC (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
int startX, startX;
int endX, endY;
int displayX, displayY;
int truedisplayY;
int map;
int i;
int sts = startX;
int color = MakeColor(255,0,0);

for (i=startX; i<=endX; i++)
{
truedisplayY = ((endY - startY)/(endX - startX)) * (sts - startX) + startY;
displayY = RoundRealToNearestInteger(truedisplayY);
displayX = sts;

CanvasClear(panel, PANEL_CANVAS, VAL_ENTIRE_OBJECT);
CanvasDrawBitmap(panel, PANEL_CANVAS, map, VAL_ENTIRE_OBJECT, MakeRect(0,0, VAL_KEEP_SAME_SIZE, VAL_KEEP_SAME_SIZE);
SetCtrlAttribute(panel, PANEL_CANVAS, ATTR_PEN_COLOR, color);
SetCtrlAttribute(panel, PANEL_CANVAS, ATTR_PEN_FILL_COLOR, color);
CanvasDrawRect(panel, PANEL_CANVAS, MakeRect(displayY, displayX, 5, 5), VAL_DRAW_FRAME_AND_INTERIOR);
sts = sts + 1;
Delay(1);
}

return 0;
}

thx
Florian
0 Kudos
Message 1 of 6
(3,862 Views)
Some hints about the code.

In the for loop, you have defined truedisplayY as integer, that means that you are rounding its value during calculation (and you can arrive to strange results since values can be promoted to integer in a moment you don't expect to during calculus). In this respect, using RoundRealToNearestInteger has no effect at all (in effect, the function accepts a double in input...).

In your code you are redrawing the whole bitmap at every step: wouldn't be better to draw only the rectangle area of the "men" on the map? You could save in memory at every step the portion covered by the man, changing your code this way:
- redraw the map portion from memory (so deleting "man" image)
- save new portion of the map in memory
- draw man position
This could reduce the amount of resources spent in graphic video I/O and maybe help you in discovering why your application hangs.

Last item: your function is a very long loop; if you don't insert a ProcessSystemEvent or at least a ProcessDrawEvents inside the loop, all updates to UIR are not processed until the loop ends: that's why your "man" doesn't appear on the map.

Message Edited by Roberto Bozzolo on 06-13-2005 03:10 PM



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 6
(3,856 Views)
thx.

At first truedisplay is declared in my program as an float. I only wrote it here wrong. Sorry! but I will look after. Thx.

to the second:
Good idea to keep the rectangle (of the "man") in memory, and only redraw this few pixels, but with which function can I realise that?
Thanks for your effort.

kind regards
Florian
0 Kudos
Message 3 of 6
(3,847 Views)
Supposing your map is not subject to change, you can simply save the whole image in a static bitmap with GetCtrlBitmap at the beginning of the program and then update the control with these functions (supposing a "man" made by a rectangle 10 by 10 pixels):

// Draw a subset of the original map
CanvasDrawBitmap (panel, PANEL_CANVAS, bitmap, MakeRect (y, x, 10, 10), MakeRect (y, x, VAL_KEEP_SAME_SIZE, VAL_KEEP_SAME_SIZE)); // Restore original map

// Draw the "man"
CanvasDrawRect (panel, PANEL_CANVAS, MakeRect (y, x, 10, 10), VAL_DRAW_FRAME_AND_INTERIOR);


In case you need to modify the map during the program, simply save the bitmap again after modifying the map (and before drawing the "man" on it).


Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 4 of 6
(3,840 Views)
Florian,

A couple of points:

1. Whether you need to call ProcessDrawEvents or not between each iteration of the loop is governed by the canvas draw policy (ATTR_DRAW_POLICY). If you set it to "Update Immediately" or "Direct to Screen" you shouldn't need to call ProcessDrawEvents, but if you set it to "Mark for Update" then you do need to call ProcessDrawEvents (or ProcessSystemEvents). You should experiment with these modes and see which works best for you.

2. Roberto already gave you a good suggestion for not drawing the entire map each time. Another suggestion along those lines involves removing the need to redraw any part of the map at all. The way you would do that would be to set the pen mode (ATTR_PEN_MODE) to VAL_XOR_MODE before you start drawing the rects. Each time you want to move the rect, you simply redraw the rect in the previous position (which will erase it), and then draw it again in the new position. The only caveat is that you can't rely on a solid color for the rectangle. It will behave like a cursor does when it moves over a non-unoform background.

Luis
NI
0 Kudos
Message 5 of 6
(3,834 Views)
Thanks to you both,

with a mixture of your answer the program works got and fast enough.

mfg Florian
0 Kudos
Message 6 of 6
(3,821 Views)