L'algoritmo standard è 2D-DDA e 3D-DDA. Ciò restituisce ogni cella intersecata in una griglia 2D o 3D. L'algoritmo di Bresenham è più per il rendering di linee.
Pseudo-codice approssimativo per un raggio (per una linea basta fermarsi alla fine impostando minBoundary e maxBoundary come casella di delimitazione della linea.Questo fermerà sia dalla griglia che dalla fine):
var rayPosition = { x: 25, y: 25 };
var rayDirection = { x: 1, y: 1 };
var cellSize = 50;
var cell = { x: Math.floor(rayPosition.x / cellSize), y: Math.floor(rayPosition.y / cellSize) };
var step = { x: Math.sign(rayDirection.x), y: Math.sign(rayDirection.y) }; // sign returns -1, 0, or 1
var offsetFromAxis =
{
x: step.x > 0 ? cellSize - (rayPosition.x - Math.floor(rayPosition.x / cellSize) * cellSize) : (rayPosition.x - Math.floor(rayPosition.x / cellSize) * cellSize),
y: step.y > 0 ? cellSize - (rayPosition.y - Math.floor(rayPosition.y / cellSize) * cellSize) : (rayPosition.y - Math.floor(rayPosition.y / cellSize) * cellSize)
};
var tMax = { x: offsetFromAxis.x / Math.abs(rayDirection.x), y: offsetFromAxis.y / Math.abs(rayDirection.y) };
var tDelta = { x: cellSize / Math.abs(rayDirection.x), y: cellSize / Math.abs(rayDirection.y) };
var minBoundary = { x: -1, y: -1 }; // for a line just do something like (might be off by one):
/* var minBoundary =
{
x: Math.max(0, Math.min(Math.floor(lineStart.x / cellSize), Math.floor(lineEnd.x / cellSize)) - 1,
y: Math.max(0, Math.min(Math.floor(lineStart.y / cellSize), Math.floor(lineEnd.y / cellSize)) - 1
}
*/
var maxBoundary = { x: width + 1, y: height + 1 }; // for a line just do something like (might be off by one):
/* var maxBoundary =
{
x: Math.min(width, Math.max(Math.floor(lineStart.x / cellSize), Math.floor(lineEnd.x / cellSize)) + 1,
y: Math.min(height, Math.max(Math.floor(lineStart.y / cellSize), Math.floor(lineEnd.y / cellSize)) + 1
}
*/
var boundary = { x: step.x > 0 ? maxBoundary.x : minBoundary.x, y: step.y > 0 ? maxBoundary.y : minBoundary.y };
var cells = [];
do
{
cells.push({ x: cell.x, y: cell.y });
if (tMax.x < tMax.y)
{
cell.x += step.x;
if (cell.x == boundary.x)
{
break;
}
tMax.x += tDelta.x;
}
else
{
cell.y += step.y;
if (cell.y == boundary.y)
{
break;
}
tMax.y += tDelta.y;
}
} while (true);
Il 3D-DDA è quasi identico aggiungendo un asse z. (Puoi trovare esempi anche online). L'unico grande cambiamento è l'istruzione if:
if (tMax.x < tMax.y)
{
if (tMax.x < tMax.z)
{
// x
}
else
{
// z
}
}
else
{
if (tMax.y < tMax.z)
{
// y
}
else
{
// z
}
}
Per quanto riguarda le strutture dati, puoi semplicemente usare una matrice 1D e indicizzarla con qualcosa di simile:
index = z * xDimensione * yDimensione + y * xDimensione + x;
Non sei sicuro di quale sia la tua applicazione esatta, ma dovrebbe essere sufficiente.