Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Re: looking for a hexagon tiling module

Reply
Thread Tools

Re: looking for a hexagon tiling module

 
 
Peter J. Holzer
Guest
Posts: n/a
 
      04-07-2012
["Followup-To:" header set to comp.lang.perl.misc.]
On 2012-04-06 18:37, Eli the Bearded <*@eli.users.panix.com> wrote:
> I'd like a module to manipulate co-ordinates on an X,Y plane that
> have an overlapping hexagon grid. Consider, for example, a game
> that uses a hexagonal grid to move around. Chinese Checkers (star
> halma) is one such game. You would want functions to turn a mouse
> click into a hexagon tile id of some sort, and you'd want functions
> to calculate how to draw the tiles if the side is S pixels, or
> if you want to fit N tiles across on a M wide field.
>
> I don't want to implement a game, I do want to be able to divide a
> pixel plane into hexagons, calculate which pixels would be interior,
> which pixels would be a border, know which hexagons are complete
> and which are clipped. I don't want something that is tied to a
> particular drawing system, because it probably won't be the one I
> want to use.

[...]
> As an example, here's this bit of ASCII art I must have spent
> all of five minutes on. The hexagonal tiles are numbered with
> example coordinates. There is a image area superimposed upon
> this grid with a border of : + and =. The upper left hand corner
> is about one quarter of the 0,0 hex grid. Cell 1,2 is the upper-
> most, leftmost full hexagon, cell 1,1 is the leftmost, upper-
> most full hexagon. 12 characters right and 16 down from the +
> in the image corner is the * in cell 3,2. 18 characters right
> and 5 down from the + is the L on the border of 0,3 and 1,3.
>
> ___ ___ ___ ___
> / \ / \ / \ / \
> / \ / \ / \ / \
> / 0,0 \___/ 0,2 \___/ 0,4 \___/ 0,6 \_
> \ +===/===\=======/===\=======/===\=======/=
> \ : / \ / \ / \ /
> \_:_/ 0,1 \___/ 0,3 \___/ 0,5 \___/
> / : \ / \ / \ / \
> / : \ / \ / \ / \
> / 1,0 \___/ 1,2 \_L_/ 1,4 \___/ 1,6 \_
> \ : / \ / \ / \ /
> \ : / \ / \ / \ /
> \_:_/ 1,1 \___/ 1,3 \___/ 1,5 \___/
> / : \ / \ / \ / \
> / : \ / \ / \ / \
> / 2,0 \___/ 2,2 \___/ 2,4 \___/ 2,6 \_
> \ : / \ / \ / \ /
> \ : / \ / \ / \ /
> \_:_/ 2,1 \___/ 2,3 \___/ 2,5 \___/
> / : \ / \ / \ / \
> / : \ / * \ / \ / \
> / 3,0 \___/ 3,2 \___/ 3,4 \___/ 2,6 \_
> \ : / \ / \ / \ /
> \ : / \ / \ / \ /
> \_:_/ 3,1 \___/ 3,3 \___/ 3,5 \___/
> / : \ / \ / \ / \
>


I took that as a challenge for a bit of weekend programming

It doesn't do everything you want (must leave some of the fun to you)
but it should get you started:


package Math::HexGrid;

use warnings;
use strict;
use 5.010;
use POSIX qw(floor);

our $VERSION = 0.001;

sub new {
my ($class, $s, $h) = @_;

# $s is the length of a side of a cell,
# $h is the height of half a cell.
# we can compute that from $s or let the user specify it.
$h = int($s * sqrt(3) / 2) unless defined $h;
my $self = { s => $s, h => $h };
bless $self, $class;
return $self;
}

sub center_of_hex {
my ($self, $ind_x, $ind_y) = @_;

my ($s, $h) = @{$self}{'s', 'h'};
my ($px_x, $px_y);

# That's simple. The horizontal differenc between the center of
# (0,0) and (0,2) is obviously 3 * $s. (0,1) sits between them
# but is offset by $h in the y axis.
if ($ind_x % 2 == 0) {
$px_x = $ind_x * 3/2 * $s;
$px_y = $ind_y * 2 * $h;
} else {
$px_x = $ind_x * 3/2 * $s;
$px_y = ($ind_y * 2 + 1) * $h;
}
return ($px_x, $px_y);
}

sub hex_from_coord {
my ($self, $px_x, $px_y) = @_;

my ($s, $h) = @{$self}{'s', 'h'};

# Not quite as simple, but if you squint a bit
# you can see that the pattern repeats every
# 3 * $s horizontally and every 2 * $h vertically.
# so we split the plane into rectangles of this size
my $seg_x = floor($px_x / (3 * $s));
my $seg_y = floor($px_y / (2 * $h));
my $rel_x = $px_x - $seg_x * 3 * $s;
my $rel_y = $px_y - $seg_y * 2 * $h;

my ($ind_x, $ind_y);

# and then we split those rectangles into vertical stripes
# again.
# Everything between +/- 0.5 $s horizontally from the center of a
# cell belongs to that cell.
# but between that the cells overlap and we have to check on which
# side of the diagonals the pixel is.
given ($rel_x) {
when ($_ < 0.5 * $s) {
$ind_x = $seg_x * 2;
$ind_y = $seg_y + ($rel_y >= $h);
}
when ($_ < 1 * $s) {
my $r_x = ($_ - $s / 2) / ($s / 2);
my $r_y = abs(($rel_y - $h) / $h);
if ($r_y < $r_x) {
$ind_x = $seg_x * 2 + 1;
$ind_y = $seg_y;
} else {
$ind_x = $seg_x * 2;
$ind_y = $seg_y + ($rel_y >= $h);
}
}
when ($_ < 2 * $s) {
$ind_x = $seg_x * 2 + 1;
$ind_y = $seg_y;
}
when ($_ < 2.5 * $s) {
my $r_x = (2.5 * $s - $_) / ($s / 2);
my $r_y = abs(($rel_y - $h) / $h);
if ($r_y < $r_x) {
$ind_x = $seg_x * 2 + 1;
$ind_y = $seg_y;
} else {
$ind_x = $seg_x * 2 + 2;
$ind_y = $seg_y + ($rel_y >= $h);
}
}
when ($_ < 3 * $s) {
$ind_x = $seg_x * 2 + 2;
$ind_y = $seg_y + ($rel_y >= $h);
}
}
return ($ind_x, $ind_y);

}

1;

hp

PS: I did see Derek's posting just before posting this, but afaics he
concentrates on rendering graphics while my code does just geometry, no
graphics at all (although I've also written a small test script to
create a PNG with hex-tiles).

--
_ | Peter J. Holzer | Deprecating human carelessness and
|_|_) | Sysadmin WSR | ignorance has no successful track record.
| | | |
__/ | http://www.hjp.at/ | -- Bill Code on
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: looking for a hexagon tiling module Mart van de Wege Perl Misc 0 04-08-2012 01:07 PM
stretching the background image instead of tiling =?Utf-8?B?U3JpZGhhcg==?= ASP .Net 3 11-30-2005 11:32 AM
Printable tiling - Not tiling on screen needed. SS4 Computer Support 7 12-23-2003 03:05 AM
[ann] prime-patterns; hexagon-0.1 Simon Strandgaard Ruby 2 10-07-2003 04:35 PM
Re: Repeating a tiling image in a table cell Anders Thorsen Holm HTML 0 07-15-2003 08:22 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57