Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2003:
[Freeciv-Dev] Re: (PR#4004) A canvas_iterate macro for mapview
Home

[Freeciv-Dev] Re: (PR#4004) A canvas_iterate macro for mapview

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jdorje@xxxxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#4004) A canvas_iterate macro for mapview
From: "rwetmore@xxxxxxxxxxxx" <rwetmore@xxxxxxxxxxxx>
Date: Sat, 19 Apr 2003 08:32:41 -0700
Reply-to: rt@xxxxxxxxxxxxxx

I think that the following shows what should not be in the basic loop
macro, rather than what should be. The problem is one of separation of
functionality, and not trying to overload something with every special
case possibility. GB actually has the right idea below.

Some quick points ...

Fundamentally, isometric and standard gui displays are different, and
thus at some lower level you will need different code to draw them.

Tiles should understand how to draw themselves, including all adjacent
overlaps. The problem of working out the overlaps is not a loop issue,
but one of context in the drawing process.

One should not try to draw tiles to mate up to a canvas object border.

This is a very complex process as shown below with all kinds of
special cases. Instead one should draw into a canvas backing store
that is an appropriate number of tiles larger than the ultimately
viewable window. The viewable window is then clipped to ignore all
the partially drawn outer parts, showing only the fully drawn
interior tiles.

And conclusions ...

Thus, if one rephrases the problem in a suitable way, one just has
to do a simple GB iteration over the border+viewable tiles in the
window asking them to draw themselves possibly with some context
mask that tells an individual tile-draw which adjacent positions
might be relevant.

The iteration is realtively straightforward and can probably be done
in a single way for both the isometric and standard cases using some
sort of gui_native coordinates.

The application code is responsible for handling special case lookups
into adjacent tiles if it needs them.

This generalizes nicely since the complexity is moved to the special
case application methods, and not embedded in the generic loop. One
just adds new application methods as desired for new display topologies
and never have to rewrite ugly loop code that tries to be all things
to all users and ends up just becoming an obstacle to everything :-).

Cheers,
RossW
=====

Jason Short wrote:
> Gregory Berkolaiko wrote:
> 
>>On Tue, 15 Apr 2003, Jason Short wrote:
> 
> 
>>>2.  We need to catch all tiles that overlap the area.  Even in non-iso 
>>>view you need to consider the case where (x0,y0) does not mark a tile 
>>>origin.  In iso-view it becomes quite a bit more complicated since the 
>>>tiles are aligned isometrically, and you need to account for the extra 
>>>UNIT_TILE_HEIGHT area (which is one reason why having a draw_type 
>>>parameter would be helpful - to allow the users to filter out unwanted 
>>>tiles).
>>
>>
>>I drew a couple of iso example on a piece of paper and I think that
>>"catching all tiles that overlap" can produce rather strange shapes.  I
>>think "all tiles whose centers are in the rectangle" is both nicer 
>>visually and easier to implement.
> 
> 
> Yes, it certainly does give some strange shapes.  Unfortunately just 
> catching those with centers in the rectangle is not too helpful in most 
> cases, although a wrapper could be used to get all cases.
> 
> The core problem is that in iso view, the origin of the canvas rectangle 
> may fall within any of 4 different cases:
> 
>          XX
>        XX  XX
>      XX 1  2 XX
>    XX          XX
>      XX 3  4 XX
>        XX  XX
>          XX
> 
> this figure shows the tile that covers the rectangle origin.
> 
> If the origin is at point 1 then the top-left corner of the rectangle 
> looks like:
> 
>       X X
>      * X     where * is the origin tile.
>     X X X
>      X X
> 
> in case 2 it becomes:
> 
>     X X
>    * X X
>     X X
>    X X X
> 
> in case 3 it is
> 
>     * X
>    X X X
>     X X
>    X X X
> 
> and in case 4
> 
>    * X X
>     X X
>    X X X
>     X X
> 
> similarly there are 4 different cases for each of the 4 corners, for a 
> total of 16 possible cases.
> 
> For the loop to know all this is no good.  Even in the above cases, case 
> 2 and 3 differs from cases 3 and 4 because the origin of the iteration 
> is on a half-tile, not a tile.  This means the compression code used to 
> get native GUI coordinates would have to be different for an exact loop.
> 
> In my ugly-but-efficient implementation, I simply expand the rectangle 
> of iteration sufficiently so that a simple loop can be used - basically 
> taking a bounding box of all the above cases.  Then I filter out the few 
> border cases that we actually don't want to find.  This filtering isn't 
> full since it only checks the bounding box of the tile to see if it 
> overlaps (so case 1 will have an extra tile in the loop).
> 
> Looking further, it's actually difficult to tell what parts of the tile 
> we're concerned about overlapping.  An isometric tile looks something like:
> 
>    XXXXXXXXXXXXXX
>    X            X
>    X     4      X
>    XXXXXXXXXXXXXX
>    X 3 XX  XX 3 X
>    X XX      XX X
>    XX     1    XX
>    X XX      XX X
>    X 2 XX  XX 2 X
>    XXXXXXXXXXXXXX
> 
> where area 1 is the base tile, area 2 may be used for units (and maybe 
> other graphics?), area 3 is used for "3d terrain" and units (and maybe 
> others), and area 4 is used only for units (but will eventually be used 
> for 3d terrain).  Any particular canvas_iterate loop will want to find 
> all tiles whose "active areas" overlap the canvas rectangle.
> 
> - For show_city_descriptions, the active area is 1+2+3.
> - For update_map_canvas_visible, the active area would be 1+2+3+4.
> - For a drag-to-select-units feature, the active area would be 1+2+3+4.
> - For a drag-to-select-tiles feature, the active area would be 1.
> 
> My only real conclusion is that this problem is hard.  But I _really_ 
> don't want these iteration loops to be duplicated throughout the code - 
> a poor/ugly implementation of canvas_iterate would be better than that 
> (at least it hides the ugliness).
> 
> jason
> 
> 
> 
> 




[Prev in Thread] Current Thread [Next in Thread]