2015-11-10 3 views
0

J'ai écrit une fonction qui calcule les points d'une courbe b-spline, en dessinant la courbe sur l'écran lorsque les points sont générés en utilisant la fonction setinterval() intégrée. Le problème est que lorsque ces points sont dessinés à l'écran, il y a simplement une partie ou un petit segment de la courbe visible le long de la courbe interpolée, mais la courbe entière ne persiste pas lorsque la courbe est tracée. En plus de cela, la courbe va traîner l'écran une fois qu'il atteint un certain point. Le code semble être conçu de telle sorte que la fonction se termine (l'intervalle sera effacé) une fois que la valeur de t atteint 1, mais pour une raison quelconque, la fonction continue d'être appelée, ce qui provoque l'animation de la courbe hors écran. Inversement, j'ai une autre fonction qui utilise simplement une boucle for pour dessiner la courbe avec les mêmes points, mais avec cette fonction, une petite courbe est tracée une fois, clairement à l'écran. Voici le code pour les deux fonctions:Problème avec l'animation de rendu b-spline en javascript

 //function that draws the spline one time 
     function bspline(context, points) { 
     context.beginPath(); 
     for (var t = 0; t < 1; t += 0.1) { 
      var ax = (-points[0].x + 3 * points[1].x - 3 * points[2].x + points[3].x)/6; 
      var ay = (-points[0].y + 3 * points[1].y - 3 * points[2].y + points[3].y)/6; 
      var bx = (-points[0].x - 2 * points[1].x + points[2].x)/2; 
      var by = (-points[0].y - 2 * points[1].y + points[2].y)/2; 
      var cx = (-points[0].x + points[2].x)/2; 
      var cy = (-points[0].y + points[2].y)/2; 
      var dx = (points[0].x + 4 * points[1].x + points[2].x)/6; 
      var dy = (points[0].y + 4 * points[1].y + points[2].y)/6; 
      context.moveTo(
       ax*Math.pow(t,3) + bx*Math.pow(t,2) + cx*t + dx, 
       ay*Math.pow(t,3) + by*Math.pow(t,2) + cy*t + dy 
       ); 
      context.lineTo(
       ax*Math.pow(t+0.1, 3) + bx*Math.pow(t+0.1, 2) + cx*(t+0.1) + dx, 
       ay*Math.pow(t+0.1,3) + by*Math.pow(t+0.1,2) + cy*(t+0.1) + dy 
       ); 
      //m.translate(ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx, ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy,0); 
     } 
     context.stroke(); 
    } 


var interval; 
    //sets the interval for the spline to be animated over 
    function drawSpline(context, points, newpts) { 
     interval = setInterval(splineAnim(context, points, newpts), 1600.67); 
     console.log("interval set"); 
    } 
    var t = 0; 

    //determines and draws the points of the spline 
    function splineAnim(context, points, newpts) { 
     // Draw curve segment 
     var ax = (-points[0].x + 3 * points[1].x - 3 * points[2].x + points[3].x)/6; 
     var ay = (-points[0].y + 3 * points[1].y - 3 * points[2].y + points[3].y)/6; 
     var bx = (-points[0].x - 2 * points[1].x + points[2].x)/2; 
     var by = (-points[0].y - 2 * points[1].y + points[2].y)/2; 
     var cx = (-points[0].x + points[2].x)/2; 
     var cy = (-points[0].y + points[2].y)/2; 
     var dx = (points[0].x + 4 * points[1].x + points[2].x)/6; 
     var dy = (points[0].y + 4 * points[1].y + points[2].y)/6; 
     context.beginPath(); 
     context.moveTo(
      ax * Math.pow(t, 3) + bx * Math.pow(t, 2) + cx * t + dx, 
      ay * Math.pow(t, 3) + by * Math.pow(t, 2) + cy * t + dy 
      ); 
     var ax2 = ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx; 
     var ay2 = ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy; 

     context.lineTo(
      ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx, 
      ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy 
      ); 
     context.stroke(); 
     //m.translate(ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx, ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy, 0); 
     //console.log("ax2: " + ax2 + ", ay2: " + ay2); 
     var arr = [ax2, ay2]; 
     newpts.push(arr); 
     t += 0.02; 

     //Reached end of curve 
     if (t > 1) clearInterval(interval); 
    } 

Répondre

1

pas un codeur JAVASCRIPT mais dans de nombreuses langues 3 signifie entier

alors essayez d'ajouter .0 à toutes les constantes flottantes ... Mon pari est que votre compilateur/interpréteur détecte un entier et tronque le résultat en changeant les sous-résultats de façon à ce que la courbe ne corresponde pas et parfois il peut sembler au dessus de 1.0 même si ce n'est pas le cas.

également mieux for arrêt pour cela est:

for (t=0.0,e=1;e;t=0.1) 
{ 
if (t>=1.0) { e=0; t=1.0; } 
// here do your stuff 
} 

De cette façon, vous pouvez utiliser une étape non seulement la division exacte de la gamme. De plus, cela prend en compte la représentation non exacte du nombre d'étapes et l'erreur d'arrondi cumulatif.

Juste quelques conseils

  • utilisant pow pour les petits exposants entiers est un énorme tueur surpuissant et la performance
  • pourquoi vous des points deux fois l'informatique? vous pouvez passer à une fois et puis juste ligne ... ou de se rappeler les dernières position x, y au lieu de calcul ...

donc quand mettre tous ensemble (C++)

int e; 
float t,tt,ttt,dt; 
vec2 a0,a1,a2,a3; // coefficients 2D vectors 
vec2 p0,p1,p2,p3; // your input control points 2D vectors 
vec2 p;   // temp point 

a0=       ( p0); 
a1=     (3.0*p1)-(3.0*p0); 
a2=   (3.0*p2)-(6.0*p1)+(3.0*p0); 
a3=( p3)-(3.0*p2)+(3.0*p1)-( p0); 

t=0.0; dt=0.1; tt=t*t; ttt=tt*t; 
p=a0+(a1*t)+(a2*tt)+(a3*ttt); 
MoveTo(p.x,p.y); 

for (t+=dt,e=1;e;t=dt) 
{ 
if (t>=1.0) { e=0; t=1.0; } 
// here do your stuff 
tt=t*t; 
ttt=tt*t; 
p=a0+(a1*t)+(a2*tt)+(a3*ttt); 
LineTo(p.x,p.y); 
} 
  • vec2 est juste vecteur 2D contenant x,y membres
+0

Merci pour la réponse! Juste quelques questions cependant. Premièrement, quel est le but de e à l'intérieur des instructions for et if et comment obtenez-vous les valeurs x et y pour p? Il semble seulement qu'il y ait une composante de p étant définie. De même, comment devrais-je déterminer quels points de contrôle devraient être utilisés pour tenir sur l'écran? merci – loremIpsum1771

+0

@ loremIpsum1771 'e' est juste la condition de fin si' t' est hors de portée alors 't' est fixé sur' 1.0' et 'e' est réinitialisé pour que la boucle s'arrête après avoir rendu le dernier point (' t = 1.0 ') vous pourriez utiliser' bool' au lieu de 'int' aussi. L'algèbre vectorielle est simple ... '3.0 * p0' est la même chose que' (3.0 * p0.x, 3.0 * p0.y) 'vous faites juste le fing par axe ... donc' p0, p1, p2, p3' est le même que vos 'points []' et 'a0, a1, a2, a3' est le même que votre' (ax, ay), (bx, par), ... ' – Spektre