Pour une application de dessin, j'enregistre les coordonnées du mouvement de la souris dans un tableau, puis je les dessine avec lineTo. La ligne résultante n'est pas lisse. Comment puis-je produire une seule courbe entre tous les points rassemblés?
J'ai cherché sur Google mais je n'ai trouvé que 3 fonctions pour dessiner des lignes: Pour 2 points d'échantillonnage, utilisez simplement lineTo
. 3 points d' échantillonnage quadraticCurveTo
, pour 4 points d' échantillonnage, bezierCurveTo
.
(J'ai essayé de dessiner un bezierCurveTo
pour 4 points dans le tableau, mais cela conduit à des plis tous les 4 points d'échantillonnage, au lieu d'une courbe continue lisse.)
Comment écrire une fonction pour dessiner une courbe lisse avec 5 points d'échantillonnage et au-delà?
Réponses:
Le problème de la jonction de points d'échantillonnage ultérieurs avec des fonctions disjointes de type «curveTo» est que la rencontre des courbes n'est pas lisse. En effet, les deux courbes partagent un point final mais sont influencées par des points de contrôle complètement disjoints. Une solution consiste à «courber» les points médians entre les 2 points d'échantillonnage suivants. Joindre les courbes à l'aide de ces nouveaux points interpolés donne une transition douce aux points d'extrémité (ce qui est un point final pour une itération devient un point de contrôle pour l'itération suivante.) En d'autres termes, les deux courbes disjointes ont beaucoup plus en commun maintenant.
Cette solution a été extraite du livre "Foundation ActionScript 3.0 Animation: Faire bouger les choses". p.95 - techniques de rendu: création de plusieurs courbes.
Remarque: cette solution ne trace pas réellement à travers chacun des points, qui était le titre de ma question (elle se rapproche plutôt de la courbe à travers les points d'échantillonnage mais ne passe jamais par les points d'échantillonnage), mais pour mes besoins (une application de dessin), c'est assez bon pour moi et visuellement vous ne pouvez pas faire la différence. Il existe une solution pour parcourir tous les exemples de points, mais c'est beaucoup plus compliqué (voir http://www.cartogrammar.com/blog/actionscript-curves-update/ )
Voici le code de dessin pour la méthode d'approximation:
la source
Un peu tard, mais pour mémoire.
Vous pouvez obtenir des lignes lisses en utilisant des splines cardinales (aka spline canonique) pour dessiner des courbes lisses passant par les points.
J'ai créé cette fonction pour la toile - elle est divisée en trois fonctions pour augmenter la polyvalence. La fonction principale du wrapper ressemble à ceci:
Pour dessiner une courbe, utilisez un tableau avec x, y points dans l'ordre:
x1,y1, x2,y2, ...xn,yn
.Utilisez-le comme ceci:
La fonction ci-dessus appelle deux sous-fonctions, une pour calculer les points lissés. Cela renvoie un tableau avec de nouveaux points - c'est la fonction principale qui calcule les points lissés:
Et pour dessiner réellement les points sous forme de courbe lissée (ou toute autre ligne segmentée tant que vous avez un tableau x, y):
Afficher l'extrait de code
Il en résulte ceci:
Vous pouvez facilement étendre le canevas pour pouvoir l'appeler comme ceci à la place:
Ajoutez ce qui suit au javascript:
Vous pouvez trouver une version plus optimisée de ceci sur NPM (
npm i cardinal-spline-js
) ou sur GitLab .la source
ptsa
devrait êtrepts
, sinon il générerait des erreurs.La première réponse ne passera pas par tous les points. Ce graphe passera exactement par tous les points et sera une courbe parfaite avec les points comme [{x:, y:}] n tels points.
la source
Comme le souligne Daniel Howard , Rob Spencer décrit ce que vous voulez sur http://scaledinnovation.com/analytics/splines/aboutSplines.html .
Voici une démo interactive: http://jsbin.com/ApitIxo/2/
Ici, c'est comme un extrait au cas où jsbin serait en panne.
la source
J'ai trouvé que cela fonctionnait bien
la source
Je décide d'ajouter, plutôt que de publier ma solution dans un autre article. Voici la solution que je construis, peut-être pas parfaite, mais jusqu'à présent, le rendement est bon.
Important: il passera par tous les points!
Si vous avez une idée, pour l' améliorer , partagez-la avec moi. Merci.
Voici la comparaison d'avant après:
Enregistrez ce code au format HTML pour le tester.
la source
Essayez KineticJS - vous pouvez définir une spline avec un tableau de points. Voici un exemple:
Ancienne URL: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
Voir l'url de l'archive: https://web.archive.org/web/20141204030628/http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
la source
Incroyablement tardive mais inspirée par la réponse brillamment simple de Homan, permettez-moi de poster une solution plus générale (générale dans le sens où la solution de Homan plante sur des tableaux de points avec moins de 3 sommets):
la source
Pour ajouter à la méthode des splines cardinales de K3N et peut-être répondre aux préoccupations de TJ Crowder concernant le `` trempage '' des courbes à des endroits trompeurs, j'ai inséré le code suivant dans la
getCurvePoints()
fonction, juste avantres.push(x);
Cela crée effectivement une boîte englobante (invisible) entre chaque paire de points successifs et garantit que la courbe reste dans cette boîte englobante - c.-à-d. si un point de la courbe est au-dessus / en dessous / à gauche / à droite des deux points, il modifie sa position pour être dans la boîte. Ici, le point médian est utilisé, mais cela pourrait être amélioré, peut-être en utilisant une interpolation linéaire.
la source
Si vous souhaitez déterminer l'équation de la courbe passant par n points, le code suivant vous donnera les coefficients du polynôme de degré n-1 et enregistrera ces coefficients dans le
coefficients[]
tableau (à partir du terme constant). Les coordonnées x n'ont pas à être dans l'ordre. Ceci est un exemple de polynôme de Lagrange .la source