in reply to Re: Implementation of a QuadTree and worries of a lone programmer
in thread RFC: Implementation of a QuadTree and worries of a lone programmer

What it'll be used for is this: I want to make use of OpenGL occlusion routines to determine which parts of the world can be skipped in drawing. For that i need to create a rough shape around the parts that would be drawn, keeping it cheap enough to actually make a difference. That shape is created by taking all units that would contain something and drawing shapes around them.

I could go the naive way and draw one cube per unit and call it a day. However that would be rather slow and i'd prefer to draw a rectangular shape that encompasses as many units as possible.

To give an example on practice, with a map such as this:
0 4 8 12 15 00111000000000000 1111000000000000 1111000000000000 1111000000000000 40000000000000000 0000000000000000 0000000000000000 0000000000000000 80000000000000000 0000000000000000 0000000000000000 0000000000000000 120000000000000000 0000000000000000 0000000000000000 150000000000000000
, the result would be: 0:3:2:3|2:3:0:1|0:1:1:1|1:1:0:0|. This would be 4 shapes as opposed to the 15 shapes needed if i were drawing this naively.

I'm not sure at all what you mean in your example in the first place. But my guts tell me that you kinda missed the point. Also, i have no idea about how to use inline-c.

Edit: I should also note, the grid won't get bigger. At least not in my application. 16x16 is the limit on the data i have. I merely made it work for general cases in case others might find it useful and because i found it easier to work that way.

Replies are listed 'Best First'.
Re^3: Implementation of a QuadTree and worries of a lone programmer
by eric256 (Parson) on Nov 07, 2008 at 18:57 UTC

    I don't understand your notation there "0:3:2:3|2:3:0:1|0:1:1:1|1:1:0:0|", but can't you draw the area with 1's as two objects one large tall one and one small tall one? (1,0)-(3,3) and (0,1)-(0,3) or of course you could split it the other way (0,1)->(3,3) and (1,0)->(3,0).


    ___________
    Eric Hodges
      The notation comes from this:
      $rectangles .= "$child->{XMIN}:$child->{XMAX}:$child->{YMIN}:$child->{YMAX}|";

      As for it being condensable into two rectangles: Yes, i am aware of that. Just haven't gotten around to implementing that last bit of optimization. :)

      Reason for that being that i was only made aware of a decently fast way to do it an hour ago.

        I was looking at the QuadTree stuff and I wonder if you wouldn't be better off just using some soft of fill technique instead. I've thrown together and example, its fast and it automaticaly builds the biggest rectangles it can. I think it might be better for your needs. It is not optomized in any way and could definitly have some parts combined together, but it works nice

        #!/bin/perl use strict; use warnings; use Data::Dumper; my $grid = [[0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0], [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0], [1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0], [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0], [0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0], [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], ]; sub get_area { my $sel_area = 0; my ($grid, $x1, $y1, $x2, $y2) = @_; for my $x ($x1..$x2) { for my $y ($y1..$y2) { $sel_area++ if $grid->[$x][$y] eq "1"; } } return $sel_area; } sub sel_area { my $sel_area = 0; my ($grid, $label,$x1, $y1, $x2, $y2) = @_; die unless defined $x1 and defined $y1 and defined $x2 and defined +$y2; for my $x ($x1..$x2) { for my $y ($y1..$y2) { $grid->[$x][$y] = $label; } } return $sel_area; } my ($min_x , $min_y,$max_x, $max_y) = (0,0,15,15); my $area = get_area($grid, $min_x, $min_y,$max_x, $max_y); my $sel_area = 0; sub print_grid { my $grid = shift; for my $row (@$grid) { for my $item (@$row) { print( $item eq '0' ? '.' : $item ); } print "\n"; } } print "Selected area: $area\n"; print_grid($grid); print "\n", "X" x 16, "\n\n"; my ($s_x, $s_y) = ($min_x, $min_y); my $boxes; my $l = 'a'; while ($sel_area < $area) { if ($grid->[$s_x][$s_y] eq "1") { my ($t_x,$t_y) = ($s_x, $s_y); while (1) { last if ($grid->[$t_x+1][$s_y] ne '1'); $t_x++; } while (1) { $t_y++; my ($trial_area, $real_area) = ( get_area($grid, $s_x, $s_y, $t_x, $t_y), ( ($t_x - $s_x + 1) * ($t_y - $s_y + 1) ) ); if ($trial_area < $real_area) { $t_y--; last; }; } $sel_area += get_area($grid, $s_x, $s_y, $t_x, $t_y); sel_area($grid, $l, $s_x, $s_y, $t_x, $t_y); push @$boxes, [ $s_x, $s_y, $t_x, $t_y ]; $l ++; } last if $sel_area == $area; $s_x++; if ($s_x > $max_x) { $s_x = $min_x; $s_y++; if ($s_y > $max_y) { die "Failed" } } } print_grid($grid); print "\n"; print Dumper($boxes);
        And that outputs:
        Selected area: 38 .111............ 1111............ 1111........1... 1111............ ................ ................ ................ .........1111... ...........11... ...........11... ............111. ..1111......111. ..1111.......... ................ ................ ................ XXXXXXXXXXXXXXXX .bbb............ aaaa............ aaaa........f... aaaa............ ................ ................ ................ .........dddd... ...........ee... ...........ee... ............ggg. ..cccc......ggg. ..cccc.......... ................ ................ ................ $VAR1 = [ [ 1, 0, 3, 3 ], [ 0, 1, 0, 3 ], [11, 2,12, 5 ], [ 7, 9, 7,12 ], [ 8,11, 9,12 ], [ 2,12, 2,12 ], [10,12,11,14 ] ];

        ___________
        Eric Hodges