Rectangle Tiling Algorithm





0/5 (0 vote)
This article deserves recognition for its fun potential. After reading it, I decided to try it out by building a simple HTML/JavaScript application to try it out. I used jQuery and a jQuery plugin, SVG. The work is simple and not very elegant, but I had fun putting it together.The HTML...
This article deserves recognition for its fun potential. After reading it, I decided to try it out by building a simple HTML/JavaScript application to try it out. I used jQuery and a jQuery plugin, SVG. The work is simple and not very elegant, but I had fun putting it together.
The HTML Code
Note that the references to the jQuery and SVG libraries have been shortened as if to suggest that they live in the same folder as the app. You will have to download and install these libraries and adjust these references to reflect your installation.
The library paths will have to be adjusted to yours
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Tiles</title>
<style type="text/css">
@import "C:\Users\Rodrigo\Dropbox\Silveira\SilveiraConsulting\Gildhalle\jquery\jquery.svg.package-1.4.3\jquery.svg.css";
#svgbasics { width: 400px; height: 300px; border: 1px solid #484; }
</style>
<script type="text/javascript" src="C:\Users\Rodrigo\Dropbox\Silveira\SilveiraConsulting\Gildhalle\jquery\jquery-ui-1.8.4.custom\js\jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="C:\Users\Rodrigo\Dropbox\Silveira\SilveiraConsulting\Gildhalle\jquery\jquery.svg.package-1.4.3\jquery.svg.js"></script>
<script type="text/javascript" src="tiling_1.js"></script>
</head>
<body>
<h1>Tiling</h1>
<h2>Collect the information</h2>
<div>
<div id="collectTilingInformation" >
<form id="collectTilingInformationForm" style="width: 99%">
<input type="hidden" name="Hidden" value="hiddenValue"></input>
<table>
<tbody>
<tr>
<td>Tiles</td>
</tr>
<tr>
<td><input name="numberOfTiles" type="text" value="6"></input></td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
<h2>Show the Tiles</h2>
<div id="svgbasics"></div>
<div id="collectTilingInformationForm" class="im_buttons_right">
<button type="button" id="tiles">Generate Tiles</button>
</div>
</html>
JS
/**
* @param iReactangles The number of tiles to generate
* @returns oTiles An array of integers, where each integer represents the number
* of tiles of the row represented by its index
*/
$(function() {
$('#svgbasics').svg({onLoad: drawInitial_1});
$('#tiles').click(drawTiles);
$('#clear').click(function() {
$('#svgbasics').svg('get').clear();
});
//$('#export').click(function() {
//var xml = $('#svgbasics').svg('get').toSVG();
//$('#svgexport').html(xml.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'));
//});
});
function drawInitial_1(svg) {
}
var colours = ['purple', 'red', 'orange', 'yellow', 'lime', 'green', 'blue', 'navy', 'black'];
function drawTiles() {
var i = 0;
//Get the jQuery SVG drawing area
var svg = jQuery('#svgbasics').svg('get');
//Get the number of tiles to draw
var formValues = {};
var $inputs = jQuery('#collectTilingInformationForm :input');
$inputs.each(function() {
formValues[this.name] = jQuery(this).val();
});
iTiles = formValues.numberOfTiles
console.log("Number of Tiles to draw: " + iTiles);
//Get an array where each entry represents a row and the entry value the number
//of tiles to draw for the row
tiles = tileRectangularArea(iTiles);
for (i in tiles) {
console.log("Tiles in row " + (i + 1) + ": " + tiles[i]);
}
//Clear the existing tiles
jQuery('#svgbasics').svg('get').clear();
//Get the dimensions of the drawing area
drawingAreaHeight = jQuery('#svgbasics').height();
drawingAreaWidth = jQuery('#svgbasics').width();
console.log("Drawing area height: " + drawingAreaHeight);
console.log("Drawing area width: " + drawingAreaWidth);
//Draw the tiles
var iTileX = 0;
var iTileY = 0;
for (i in tiles) {
//Get the number of tiles for this row
iTilesInRow = tiles[i];
//Calculate the dimensions of the tiles for this row
tilesHeight = Math.floor(drawingAreaHeight/iTilesInRow);
tilesWidth = Math.floor(drawingAreaWidth/iTilesInRow);
console.log("Tiles height for row " + i + ": " + tilesHeight);
console.log("Tiles width for row " + i + ": " + tilesWidth);
//Draw the tiles for this row
for (j = 0; j < iTilesInRow; j++) {
//Draw a tile
svg.rect(iTileX, iTileY,tilesWidth, tilesHeight,
{fill: colours[random(9)], stroke: colours[random(9)],
'stroke-width': random(5) + 1});
//Compute drawing coordinate x of the next tile to the right of the
// one just drawn
iTileX += tilesWidth;
}
//Set the tiles' drawing coordinates for the next row to be drawn
iTileX = 0;
iTileY += tilesHeight;
}
}
function random(range) {
return Math.floor(Math.random() * range);
}
/**
* A function to compute the number of tiles to be drawn into a rectangle
* Posted to the Code Project by Ataul Mukit
* See: http://www.codeproject.com/Tips/149445/Rectangle-Tiling-Algorithm.aspx
* @param iRectangles
* @returns
*/
function tileRectangularArea(iRectangles) {
var i = 0,
iSections = 0,
aColumnsPerRow = null,
fRoot = 0.0,
fSquareRoot = 0.0,
iRoundedRoot = 0,
iRowCount = 0,
iColCount = 0,
iLeftOver = 0,
iLeft = 0,
oTiles = null;
if (iRectangles == 0) {
//do nothing
}
else {
aColumnsPerRow = [];
if (iRectangles <= 4) {
aColumnsPerRow[0] = iRectangles
}
else {
fRoot = iRectangles * 1.0;
fSquareRoot = Math.sqrt(fRoot)
iRoundedRoot = Math.floor(fSquareRoot);
iRowCount = iRoundedRoot;
iColCount = iRoundedRoot;
iLeftOver = iRectangles - iRowCount*iColCount;
iDistribution = Math.floor(iLeftOver/iRowCount);
iColCount += iDistribution;
iLeft = iRectangles - iRowCount*iColCount;
iStartAddingIndex = iRowCount - iLeft;
for (i = 0; i < iRowCount; i++) {
if (i == iStartAddingIndex) {
iColCount++;
iStartAddingIndex = -1;
}
aColumnsPerRow[i] = iColCount;
}
}
}
return aColumnsPerRow;
}