Here is some commented PHP.... I don't claim it is the fastest possible implementation, just one I considered elegant by not having to check distances or to discard false results.
</font><blockquote>code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">
/* This function validates the input values
* It checks to see if the hex address is 4 chars long and an is an integer.
* It checks to see if the range is 1-6.
* If the criteria are all true, the function returns true, otherwise it returns false.
* It should have no side effects.
*/
function validate_input($hexAddr, $rng)
{
if((intval($hexAddr) == 0) || (strlen($hexAddr) != 4))
{
echo '<br>address incorrect<br>' . strlen($hexAddr) . " : " . intval($hexAddr);
return false;
}
if (($rng > 6) || ($rng < 1))
{
echo '<br>range incorrect<br>';
return false;
}
return true;
}
if($nucleusHex) // if you have a hex to work with
{
// validate user input
if(validate_input($nucleusHex, $range)) // validate the input
{
// determine the x and y components of the 4 digit hex address (from 0101 to 3240)
$xCoord = substr($nucleusHex, 0, 2);
$yCoord = substr($nucleusHex, 2, 2);
// realize that the maximum range in y is in the row of the specified nucleus (origin) hex
// and at that point, it is equal to twice the range entered by the user plus one
$maxRangeY = $range * 2 + 1;
echo '<br>Center System:<b> ' . $xCoord . $yCoord . '</b> Range: <b>' . $range . '</b><hr>';
// now, step through all the possible columns (called xRow, but it is really a column)
// from nucleus hex x value minus range to x value plus range
for ($xRow = ($xCoord - $range); $xRow <= ($xCoord + $range); $xRow++)
{
// calculate the distance from the nucleus row
$xD = abs(($xRow-$xCoord)); // xD is distance from our nucleus hex row
// the range of y values that is appropriate at any location is
// the maxiumum range in Y minus the displacement in x
$rangeY = $maxRangeY - $xD;
/*******************************************************************
There are eight cases of interest.... the three degrees of freedom
which apply are: The original coordinates (odd or even hex column),
the current column coordinate, and whether the maximum range in Y is
an even or odd value.
With these three degrees of freedom, eight cases are generated:
Even Max Range in Y - Start xCoord Odd - Current Row Odd
Even Max Range in Y - Start xCoord Odd - Current Row Even
Even Max Range in Y - Start xCoord Even - Current Row Odd
Even Max Range in Y - Start xCoord Even - Current Row Even
Odd Max Range in Y - Start xCoord Odd - Current Row Odd
Odd Max Range in Y - Start xCoord Odd - Current Row Even
Odd Max Range in Y - Start xCoord Even - Current Row Odd
Odd Max Range in Y - Start xCoord Even - Current Row Even
In each case, a slightly different value for the upper and lower valid
Y coordinates is required. So, go calculate them.
*********************************************************************/
if($maxRangeY % 2) // Max Range is Odd
{
if($xCoord % 2) // Starting Coord is Odd
{
if($xRow % 2) // Current Row is Odd
{
$yUpperLim = $yCoord - (0.5 * $rangeY) + 0.5;
$yLowerLim = $yCoord + (0.5 * $rangeY) - 0.5;
}
else // Current Row is Even
{
$yUpperLim = $yCoord - (0.5 * $rangeY);
$yLowerLim = $yCoord + (0.5 * $rangeY) - 1.0;
}
}
else // Starting Coord is Even
{
if($xRow % 2) // Current Row is Odd
{
$yUpperLim = $yCoord - (0.5 * $rangeY) + 1.0;
$yLowerLim = $yCoord + (0.5 * $rangeY);
}
else // Current Row is Even
{
$yUpperLim = $yCoord - (0.5 * $rangeY) + 0.5;
$yLowerLim = $yCoord + (0.5 * $rangeY) - 0.5;
}
}
}
else // Max Range is Even
{
if($xCoord % 2) // Starting Coord is Odd
{
if($xRow % 2) // Current Row is Odd
{
$yUpperLim = $yCoord - (0.5 * $rangeY) + 0.5;
$yLowerLim = $yCoord + (0.5 * $rangeY) - 0.5;
}
else // Current Row is Even
{
$yUpperLim = $yCoord - (0.5 * $rangeY);
$yLowerLim = $yCoord + (0.5 * $rangeY);
}
}
else // Starting Coord is Even
{
if($xRow % 2) // Current Row is Odd
{
$yUpperLim = $yCoord - (0.5 * $rangeY);
$yLowerLim = $yCoord + (0.5 * $rangeY);
}
else // Current Row is Even
{
$yUpperLim = $yCoord - (0.5 * $rangeY) + 0.5;
$yLowerLim = $yCoord + (0.5 * $rangeY) - 0.5;
}
}
}
// Having calculated the y coordinates upper and lower that are
// appropriate, step through the available range
for ($yRow = $yUpperLim; $yRow <= $yLowerLim; $yRow++)
{
$xResult = $xRow;
$yResult = $yRow;
// compensate for shifts that have pushed us into the negatives (happens in top hexrows of sector or
// the lowermost columns)
if ($xResult < 0)
{
$xResult += 32;
}
if ($yResult < 0)
{
$yResult += 40;
}
// compensate for lapping over into the sector below (or to the right)
$xResult = $xResult % 32;
$yResult = $yResult % 40;
if (($xResult % 32) == 0)
{
$xResult = 32;
}
if (($yResult % 40) == 0)
{
$yResult = 40;
}
// print out the coordinates
printf("<br><b>%02.0f</b>", $xResult);
printf("<b>%02.0f</b>", $yResult);
}
echo '<hr>';
}
}
}
?></pre>[/QUOTE]