Tracciamento sullo schermo

Il tracciamento della curva sullo schermo presenta un problema: la curva è parametrica e in teoria verrebbe completamente disegnata facendo variare, come ho già detto, il parametro t tra 0 e 1; però una variazione costante del parametro non provoca un corrispondente tracciamento ``continuo'' della curva (che viene disegnata ``per punti`` sullo schermo). Si potrebbe risolvere il problema considerando una variazione molto piccola del parametro (per esempio $\Delta t=10^{-6}$), ma in pratica questo provoca un aumento inutile del tempo di calcolo perché vengono generati molti punti che corrispondono allo stesso pixel sullo schermo e comunque questo non dà sufficiente garanzia che la curva non presenterà discontinuità.

Per risolvere questo problema, ho usato un piccolo trucco: prima di tracciare un punto, controllo se questo dista sullo schermo più di 1 pixel dal precedente (questo è il motivo delle discontinuità); se così non è ricalcolo un altro punto considerando una variazione del parametro più piccola (per la precisione la metà della precedente); se invece i due punti coincidono, proseguo ma nello stesso tempo raddoppio la variazione del parametro, così da evitare inutili calcoli di punti già tracciati.

La ``distanza'' che uso nella routine non è calcolata in maniera precisa: questa infatti e abbastanza pesante computazionalmente. Io uso una approssimazione (considerando xi, yi le coordinate dei due punti espresse in pixel sullo schermo):

dist= |x1-x2| + |y1-y2|

che nel mio caso è molto valida in quanto se vale 0 i punti sono coincidenti, se vale 1 i punti sono ``attaccati``, e nei restanti casi sono troppo ``lontani''.
  points=1;
  punto pu=trova_punto(cp,ncp,sta_t);
  double delta_t=.001; // esagerato... 
  int old_x=int(pu.x*xscale+.5);// first point x
  int old_y=int(pu.y*yscale+.5);// first point y
  p->setPoint(0,old_x,old_y);
  t_vec[0]=sta_t;
  double t=sta_t+delta_t;
  
  while (t<=end_t){
    bool draw=false;
    int p_x,p_y;
    int mean=0;
    while (!draw){
      pu=trova_punto(cp,ncp,t);
      p_x=int (pu.x*xscale+.5);  
      p_y=int (pu.y*yscale+.5);
      mean=( abs(old_x-p_x)+abs(old_y-p_y));
      switch(mean){
      case 0:          // punti coincidenti
        delta_t*=2;
        draw=true;
        break;
      case 1:
        draw=true;
        break;
      case 2:
        delta_t/=2; //diminusce il delta
        // Finds the point that closes the "hole" ...
        if ( (old_x-p_x)==-2){
          p->setPoint(points,p_x-1,p_y);
          t_vec[points]=t-(delta_t);
        }
        else if ( (old_x-p_x)==2){
          p->setPoint(points,p_x+1,p_y);
          t_vec[points]=t-(delta_t);
        }
        else if ( (old_y-p_y)==-2){
          p->setPoint(points,p_x,p_y-1);
          t_vec[points]=t-(delta_t);
        }
        else if ( (old_y-p_y)==2){
          p->setPoint(points,p_x,p_y+1);
          t_vec[points]=t-(delta_t);
        }
        else {
          pu=trova_punto(cp,ncp,t-delta_t);
          p->setPoint(points,int(pu.x*xscale+.5),
                      int(pu.y*yscale+.5));
          t_vec[points]=t-(delta_t);
        }
        ++points;
        draw=true;
        break;

      default:
        delta_t/=2;
        t-=delta_t;
        break;
      } //switch
    } //while(!draw)
    
    // I found a point to draw: draw it !
    if (mean){
      p->setPoint(points,p_x,p_y);
      t_vec[points]=t;
      points++;
      if ( (max_points)&&(max_points-points<10)){
        max_points+=500;
        p->resize(max_points);
        t_vec.resize(max_points);
        cerr<<"Resizing vector!"<<endl;
      }
      old_x=p_x;
      old_y=p_y;
    }
    t+=delta_t;
  }//while(t<=endt)

Tocci Giovanni 2001-09-17