Déformation de maillage par translation de points

Comment déformer un maillage en modifiant la distance des points à un centre comme s'ils étaient attirés ou repoussés par ce centre selon une force dont l'intensité dépend de la distance ? Le résultat attendu est par exemple le suivant :
Déformation d'un maillage par translation des points

La solution

Un tel effet résulte très simplement de la translation de chaque point du maillage le long de l'axe qui le relie au centre, selon un facteur à moduler en fonction de la distance initiale entre le point et le centre.

Le code JavaScript

Le maillage est décrit dans un tableau de tableaux meshBase[] où les points sont stockés sous la forme de structures {x, y} d'abord en ligne, puis en colonne. De la sorte, les coordonnées du point ligne 3 et colonne 7 sont mesh[3][7].x et mesh[3][7].y. Le tableau contient MESH_HEIGHT lignes et MESH_WIDTH colonnes de points. Il est généré de la manière suivante :
var MESH_WIDTH = 20, MESH_HEIGHT = 20;
var meshBase = new Array ();
for (j = 0; j != MESH_HEIGHT; j ++) {
	meshBase.push (new Array ());
	for (i = 0; i != MESH_WIDTH; i ++)
		meshBase[j].push ({x:Math.round (i * r.width / (MESH_WIDTH - 1)), y:Math.round (j * r.height / (MESH_HEIGHT - 1))});
}
La déformation autour d'un point O est accomplie par une fonction qui calcule l'image de chaque point M du maillage par translation le long du vecteur OM d'un facteur d / k. Dans ce facteur, d est la distance OM initiale et k est une constante, par exemple 100 (sa valeur est définie empiriquement, c'est-à-dire en fonction du résultat produit qui paraît le plus esthétique).
function meshDeform (xO, yO) {
	var i, j, xM, yM, d;
	for (j = 1; j != (MESH_HEIGHT - 1); j ++) {
		for (i = 1; i != (MESH_WIDTH - 1); i ++) {
			xM = meshBase[j][i].x;
			yM = meshBase[j][i].y;
			d = Math.sqrt ((xM - xO) * (xM - xO) + (yM - yO) * (yM - yO));
			xM = (d / k) * (xM - xO) + xO;
			yM = (d / k) * (yM - yO) + yO;
			mesh[j][i] = {x:Math.round (xM), y:Math.round (yM)};
		}
	}
	meshDraw ();
}
Les compteurs des boucles sont définis de telle manière que les points qui constituent les bordures du maillage ne subissent aucune translation. C'est une solution pour s'assurer que le résultat produit occupe quoi qu'il arrive toute la surface occupée par le maillage initial.

L'exemple

Cliquez ici pour accéder à une page de test minimaliste. Vous pourrez visualiser le code et le récupérer pour travailler avec.

Les maths

Chaque point M subit une translation le long du vecteur OM pour l'amener en N :
Translation d'un point le long d'un vecteur
Quand la translation est d'un facteur k, alors ON = k * OM. Les coordonnées de N s'en déduisent :
xN - xO = k * (xM - xO)
donc :
xN = k * (xM - xO) + xO
De même pour yN :
yN = k * (yM - yO) + yO
Le calcul est effectué pour chacun des points du maillage (exception faite des points constituant les bordures, pour la raison déjà citée). Par exemple, le point (8, 8) repoussé par le point (14, 14) :
Déformation d'un maillage par translation (avant)
Ce qui donne :
Déformation d'un maillage par translation (après)
Déformation de maillage par translation de points